Mobile App Dev 2022W: Tutorial 5
This tutorial is still being developed.
In this tutorial you will be playing with textanalyzer-3, which implements the same text analyzer functionality as Tutorial 2's textanalyzer-1 and [Mobile App Dev 2022W: Assignment 1|Assignment 1's textanalyzer-2]. This version, however, uses UIKit/Storyboard, not SwiftUI.
Getting Started
Unlike past tutorials, here we are textanalyzer-3 supplying the contents of the entire project rather than just one file. If you have problems with this project you'll need to re-create the project as follows:
- Create a new iOS (not multiplatform) App. The interface should be "Storyboard" (NOT SwiftUI) and the language should be Swift.
- Replace the contents of ViewController.swift, either by overwriting the file or copying and pasting the code below. (Copy from the raw source file, not this page.)
- Replace the contents of Main.storyboard, either by overwriting the file or by copying and pasting in the source view in Xcode by right clicking on "Main" in the Navigator pane and selecting Open As -> Source Code.
Key Concepts & APIs
Questions
Tasks
textanalyzer-3 Code
ViewController.swift
//
// ViewController.swift
// textanalyzer-3
//
// Created by Anil Somayaji on 2/3/22.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet var t: UITextField!
@IBOutlet weak var analysisMenuButton: UIButton!
@IBOutlet weak var analysisResult: UILabel!
@IBOutlet weak var appTitle: UILabel!
var analysisMode = "None"
// override func viewDidLoad() {
// super.viewDidLoad()
// }
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
setupAnalysisMenu()
updateAnalysis()
}
func setupAnalysisMenu() {
var menuItems: [UIAction] = []
for mode in analysis.keys {
let item = UIAction(title: mode) {
(action) in
self.analysisMode = mode
self.updateAnalysis()
}
menuItems.append(item)
}
let analysisMenu = UIMenu(title: "", children: menuItems)
analysisMenuButton.showsMenuAsPrimaryAction = true
analysisMenuButton.menu = analysisMenu
}
func updateAnalysis() {
if let inputText = t.text {
if let analysisFunc = analysis[analysisMode] {
let r = analysisFunc(inputText)
analysisResult.text = analysisMode + ": " + r
} else {
analysisResult.text = "Please choose an analysis mode."
}
}
}
@IBAction func doAnalysis(_ sender: Any) {
updateAnalysis()
}
}
func countUpper(s: String) -> String {
var count = 0
let upperCase: Set<Character> =
["A","B","C","D","E","F","G","H","I","J","K","L","M",
"N","O","P","Q","R","S","T","U","V","W","X","Y","Z"]
for c in s {
if (upperCase.contains(c)) {
count += 1
}
}
return String(count)
}
let analysis: [String: (String) -> String] = [
"Count": countCharacters,
"Upper Case": countUpper
]
func countCharacters(s: String) -> String {
let charcount = s.count
return String(charcount)
}
Main.storyboard
<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="19529" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
<device id="retina6_7" orientation="portrait" appearance="light"/>
<dependencies>
<plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="19519"/>
<capability name="Safe area layout guides" minToolsVersion="9.0"/>
<capability name="System colors in document resources" minToolsVersion="11.0"/>
<capability name="documents saved in the Xcode 8 format" minToolsVersion="8.0"/>
</dependencies>
<scenes>
<!--View Controller-->
<scene sceneID="tne-QT-ifu">
<objects>
<viewController id="BYZ-38-t0r" customClass="ViewController" customModule="textanalyzer_3" customModuleProvider="target" sceneMemberID="viewController">
<view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
<rect key="frame" x="0.0" y="0.0" width="428" height="926"/>
<autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
<subviews>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Text Analyzer" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="ZtZ-ps-7Ye">
<rect key="frame" x="107.33333333333333" y="130" width="213.33333333333337" height="41"/>
<fontDescription key="fontDescription" type="boldSystem" pointSize="34"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" ambiguous="YES" text="Result Area" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="1Vv-DZ-Mly">
<rect key="frame" x="170.66666666666666" y="498" width="86.999999999999972" height="21"/>
<fontDescription key="fontDescription" type="system" pointSize="17"/>
<nil key="textColor"/>
<nil key="highlightedColor"/>
</label>
<textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" placeholder="Enter Text" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="lai-Vo-ERj">
<rect key="frame" x="167.66666666666666" y="446" width="92.999999999999972" height="34"/>
<fontDescription key="fontDescription" style="UICTFontTextStyleBody"/>
<textInputTraits key="textInputTraits"/>
<connections>
<action selector="doAnalysis:" destination="BYZ-38-t0r" eventType="editingChanged" id="nO1-M0-6Er"/>
</connections>
</textField>
<button opaque="NO" contentMode="scaleToFill" ambiguous="YES" showsMenuAsPrimaryAction="YES" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="OZw-vK-PXJ">
<rect key="frame" x="164.66666666666666" y="46" width="98.999999999999972" height="30"/>
<state key="normal" title="Analysis Menu"/>
</button>
</subviews>
<viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
<color key="backgroundColor" systemColor="systemBackgroundColor"/>
<constraints>
<constraint firstItem="OZw-vK-PXJ" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="5v2-LY-EP2"/>
<constraint firstItem="6Tk-OE-BBY" firstAttribute="bottom" relation="greaterThanOrEqual" secondItem="1Vv-DZ-Mly" secondAttribute="bottom" constant="10" id="Qa6-s1-ne8"/>
<constraint firstItem="ZtZ-ps-7Ye" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="UGF-av-neF"/>
<constraint firstItem="OZw-vK-PXJ" firstAttribute="top" relation="lessThanOrEqual" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="10" id="XYA-0a-ubh"/>
<constraint firstItem="ZtZ-ps-7Ye" firstAttribute="top" relation="greaterThanOrEqual" secondItem="OZw-vK-PXJ" secondAttribute="bottom" constant="10" id="cFf-s5-fgz"/>
<constraint firstItem="1Vv-DZ-Mly" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="psz-eR-tP5"/>
<constraint firstItem="lai-Vo-ERj" firstAttribute="centerY" secondItem="8bC-Xf-vdC" secondAttribute="centerY" id="rod-O1-UBb"/>
<constraint firstItem="lai-Vo-ERj" firstAttribute="centerX" secondItem="8bC-Xf-vdC" secondAttribute="centerX" id="z38-IR-hwi"/>
</constraints>
</view>
<connections>
<outlet property="analysisMenuButton" destination="OZw-vK-PXJ" id="1Ec-3D-09d"/>
<outlet property="analysisResult" destination="1Vv-DZ-Mly" id="rO4-z7-K7C"/>
<outlet property="appTitle" destination="ZtZ-ps-7Ye" id="xVP-yj-fvd"/>
<outlet property="t" destination="lai-Vo-ERj" id="AkQ-xR-U8T"/>
</connections>
</viewController>
<placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
</objects>
<point key="canvasLocation" x="29.600000000000001" y="83.208395802098963"/>
</scene>
</scenes>
<resources>
<systemColor name="systemBackgroundColor">
<color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
</systemColor>
</resources>
</document>