Mobile App Dev 2021W: Tutorial 10

From Soma-notes
Jump to navigation Jump to search

This tutorial is due on April 12, 2021 by 11:30 AM. Please submit your answers via cuLearn using this template.

Note that this tutorial is optional. If you complete it, it will replace your lowest tutorial grade or will give you bonus points worth 50% of one tutorial (whichever improves your grade more).

Tasks/Questions

  1. Download and run Converter-SB. How similar is its execution to Converter2 from Tutorial 2? How similar to Converter2A from Tutorial 6?
  2. How are connections made between Main.storyboard and ViewController.swift? How does this compare to the connections between activity_main.xml and MainActivity.kt from Tutorial 6?
  3. How is layout specified in Main.storyboard? How similar is this to how layout was specified in Converter2 and Converter2A?
  4. How does the flow of control of Converter-SB compare to Converter2 and Converter2A?
  5. Why do you think that Converter-SB doesn't have a proper menu?
  6. Change Converter-SB so it starts with a message saying to "Choose a conversion above" in the result area and the button says "Select conversion".
  7. Using the storyboard editor, add a Label at the bottom of the screen. This label should initially be blank. It should have a center horizontal alignment, span the width of the screen, and be anchored to the bottom of the safe area. Describe the process you followed and include your modified Main.storyboard file.
  8. Modify ViewController.swift to make the label you added previously show a random encouragement message every time a conversion is selected OR if the label area is touched. This label should go blank once the user starts typing in something. Add at least three messages, such as the following:
    • You are choosing wisely!
    • Keep going! Almost there!
    • Welcome to Converter-SB!

Code

Converter-SB.zip

Conversions.swift

//  Conversions.swift

struct Converter {
    var convFrom = "From Type"
    var convTo = "To Type"
    var convert: (_ from: Double) -> Double?
    
    func formatConversion(_ from: Double) -> String {
        if let to = self.convert(from) {
            let toS = String(format: "%.3f", to)
            return "\(from) \(self.convFrom) is \(toS) \(self.convTo)."
        } else {
            return "Converting \(from) \(convFrom) to \(self.convTo) failed."
        }
    }
    
    init(_ from: String, _ to: String, _ f: @escaping (_ from: Double) -> Double?) {
        self.convFrom = from
        self.convTo = to
        self.convert = f
    }
}

func InToCM(_ inch: Double) -> Double {
    let cm = 2.54 * inch
    return cm
}

let conversions =
    ["F to C": Converter("Farenheit", "Celsius",
                         {F in return ((F - 32.0)*(5/9))}),
     "C to F": Converter("Celsius", "Farenheit",
                         {C in return ((9/5)*C + 32.0)}),
     "km to mi": Converter("kilometers", "miles",
                           {k in
                            let m = k * 0.6213712
                            return m
                           }),
     "inch to cm": Converter("inches", "centimeters",
                             InToCM)
    ]

let availConversions = [String] (conversions.keys)

ViewController.swift

//
//  ViewController.swift
//  Converter-SB
//
//  Created by Anil Somayaji on 2021-04-06.
//

import UIKit

class ViewController: UIViewController {
    @IBOutlet var fromField: UITextField!
    @IBOutlet weak var result: UILabel!
    @IBOutlet weak var convButton: UIButton!
    
    var convIndex = 0
    var conv = conversions[availConversions[0]]!

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
    }

    @IBAction func updateConversion() {
        convIndex = (convIndex + 1 ) % availConversions.count
        conv = conversions[availConversions[convIndex]]!
        convButton.setTitle("Conversion: \(availConversions[convIndex])", for: .normal)
    }
    
    @IBAction func doConversion() {
        if let fromS = fromField.text {
            if let from = Double(fromS) {
                result.text =
                    conv.formatConversion(from)
            } else {
                result.text = "Please enter a number."
            }
        }
    }
}

Main.storyboard

<?xml version="1.0" encoding="UTF-8"?>
<document type="com.apple.InterfaceBuilder3.CocoaTouch.Storyboard.XIB" version="3.0" toolsVersion="17701" targetRuntime="iOS.CocoaTouch" propertyAccessControl="none" useAutolayout="YES" useTraitCollections="YES" useSafeAreas="YES" colorMatched="YES" initialViewController="BYZ-38-t0r">
    <device id="retina4_7" orientation="portrait" appearance="light"/>
    <dependencies>
        <plugIn identifier="com.apple.InterfaceBuilder.IBCocoaTouchPlugin" version="17703"/>
        <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="Converter_SB" customModuleProvider="target" sceneMemberID="viewController">
                    <view key="view" contentMode="scaleToFill" id="8bC-Xf-vdC">
                        <rect key="frame" x="0.0" y="0.0" width="375" height="667"/>
                        <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                        <subviews>
                            <textField opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="left" contentVerticalAlignment="center" borderStyle="roundedRect" textAlignment="center" minimumFontSize="17" translatesAutoresizingMaskIntoConstraints="NO" id="VJ7-bt-qir">
                                <rect key="frame" x="0.0" y="122" width="375" height="34"/>
                                <fontDescription key="fontDescription" type="system" pointSize="14"/>
                                <textInputTraits key="textInputTraits"/>
                                <connections>
                                    <action selector="doConversion" destination="BYZ-38-t0r" eventType="editingChanged" id="WEr-SS-N11"/>
                                </connections>
                            </textField>
                            <button opaque="NO" contentMode="scaleToFill" contentHorizontalAlignment="center" contentVerticalAlignment="center" buttonType="system" lineBreakMode="middleTruncation" translatesAutoresizingMaskIntoConstraints="NO" id="QgR-df-1nY">
                                <rect key="frame" x="0.0" y="44" width="375" height="30"/>
                                <state key="normal" title="Button"/>
                                <connections>
                                    <action selector="updateConversion" destination="BYZ-38-t0r" eventType="touchUpInside" id="u10-i8-VVe"/>
                                </connections>
                            </button>
                            <label opaque="NO" userInteractionEnabled="NO" contentMode="left" horizontalHuggingPriority="251" verticalHuggingPriority="251" text="Label" textAlignment="center" lineBreakMode="tailTruncation" baselineAdjustment="alignBaselines" adjustsFontSizeToFit="NO" translatesAutoresizingMaskIntoConstraints="NO" id="QHi-YO-lly">
                                <rect key="frame" x="0.0" y="164" width="375" height="21"/>
                                <fontDescription key="fontDescription" type="system" pointSize="17"/>
                                <nil key="textColor"/>
                                <nil key="highlightedColor"/>
                            </label>
                        </subviews>
                        <viewLayoutGuide key="safeArea" id="6Tk-OE-BBY"/>
                        <color key="backgroundColor" systemColor="systemBackgroundColor"/>
                        <constraints>
                            <constraint firstItem="6Tk-OE-BBY" firstAttribute="trailing" secondItem="VJ7-bt-qir" secondAttribute="trailing" id="1By-U1-T9I"/>
                            <constraint firstItem="QgR-df-1nY" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="3rM-HL-fub"/>
                            <constraint firstItem="QHi-YO-lly" firstAttribute="top" secondItem="VJ7-bt-qir" secondAttribute="bottom" constant="8" id="4Mw-3g-c0Y"/>
                            <constraint firstItem="VJ7-bt-qir" firstAttribute="top" secondItem="QgR-df-1nY" secondAttribute="bottom" constant="48" id="IBz-Q9-HJr"/>
                            <constraint firstAttribute="trailing" secondItem="QHi-YO-lly" secondAttribute="trailing" id="LsV-b9-Mq7"/>
                            <constraint firstItem="QHi-YO-lly" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="NS2-ki-p00"/>
                            <constraint firstItem="QHi-YO-lly" firstAttribute="top" secondItem="VJ7-bt-qir" secondAttribute="bottom" constant="8" symbolic="YES" id="NX0-K4-DfK"/>
                            <constraint firstAttribute="trailing" secondItem="QgR-df-1nY" secondAttribute="trailing" id="ckB-TL-gBc"/>
                            <constraint firstItem="QgR-df-1nY" firstAttribute="top" secondItem="6Tk-OE-BBY" secondAttribute="top" constant="44" id="q2m-Gg-fyA"/>
                            <constraint firstItem="VJ7-bt-qir" firstAttribute="leading" secondItem="6Tk-OE-BBY" secondAttribute="leading" id="tT6-p8-3IJ"/>
                        </constraints>
                    </view>
                    <connections>
                        <outlet property="convButton" destination="QgR-df-1nY" id="6Dj-hw-rOA"/>
                        <outlet property="fromField" destination="VJ7-bt-qir" id="hkS-Oj-aWr"/>
                        <outlet property="result" destination="QHi-YO-lly" id="QEU-E4-Ty3"/>
                    </connections>
                </viewController>
                <placeholder placeholderIdentifier="IBFirstResponder" id="dkx-z0-nzr" sceneMemberID="firstResponder"/>
            </objects>
            <point key="canvasLocation" x="-215" y="40"/>
        </scene>
    </scenes>
    <resources>
        <systemColor name="systemBackgroundColor">
            <color white="1" alpha="1" colorSpace="custom" customColorSpace="genericGamma22GrayColorSpace"/>
        </systemColor>
    </resources>
</document>