<font color="#8A2BE2">[Udemy IOS Angela]</font> Ch9 iOS App Design Patterns and Code Structuring
===
# Ch9 Outline
* Show quiz question
* Check the answer
* Lear Swift Structures
* Model View Controller pattern
* Function input/output
* immutability


## 96. Setting up the Quizzler Project and Showing the Questions!
## 97. Checking Answers using 2-Dimensional Arrays

```swift!
//
// ViewController.swift
// Quizzler-iOS13
//
// Created by Angela Yu on 12/07/2019.
// Copyright © 2019 The App Brewery. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueButton: UIButton!
@IBOutlet weak var falseButton: UIButton!
let quiz = [
["第一題 4 加 2 等於 6", "True"],
["第二題 5 減 3 大於 1", "True"],
["第三題 3 加 8 比 10 小", "False"]
]
var questionNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
updateUI() //初始畫面就啟動函式
}
@IBAction func answerButtonPressed(_ sender: UIButton) {
let userAnswer = sender.currentTitle //True, False
let actualAnswer = quiz[questionNumber][1]
if userAnswer == actualAnswer {
print("Right")
} else {
print("Wrong")
}
if questionNumber + 1 < quiz.count {
questionNumber += 1
} else if questionNumber + 1 == quiz.count {
questionNumber = 0
}
updateUI()
}
//建立函式
func updateUI() {
questionLabel.text = quiz[questionNumber][0]
}
}
```
# 98. [Swift Deep Dive] Structures, Methods and Properties
## 第一版 寫死 struct 屬性方法

```swift!
struct 城鎮 {
//屬性
let 名字 = "台灣"
var 市民 = ["蔡英文", "馬英九"]
var 資源 = ["香蕉": 100, "鳳梨": 50, "西瓜" : 20]
func 增強防衛() {
print("來!加強防守")
}
}
//方法
var 台灣城鎮 = 城鎮()
print(台灣城鎮.市民) //["蔡英文", "馬英九"]
print("\(台灣城鎮.名字) 有 \(台灣城鎮.資源["香蕉"]!) 幾包") //台灣 有 100 幾包
台灣城鎮.市民.append("陳水扁")
print(台灣城鎮.市民.count) //3
台灣城鎮.增強防衛() //來!加強防守
```
## 不用self的話 init要多命名
```swift!
struct 城鎮 {
let 名字: String
var 市民: [String]
var 資源: [String: Int]
//不重複struct
init(城鎮名稱: String, 人們: [String], 狀態: [String: Int]) {
名字 = 城鎮名稱
市民 = 人們
資源 = 狀態
}
func 增強防衛() {
print("來!加強防守")
}
}
//套用init
var 台灣城鎮 = 城鎮(城鎮名稱: "台灣", 人們: ["蔡英文"], 狀態: ["香蕉": 100])
print(台灣城鎮) //城鎮(名字: "台灣", 市民: ["蔡英文"], 資源: ["香蕉": 100])
//套用struct
台灣城鎮.市民.append("馬英九")
print(台灣城鎮) //城鎮(名字: "台灣", 市民: ["蔡英文", "馬英九"], 資源: ["香蕉": 100])
```

## 完整
```swift!
struct 城鎮 {
let 名字: String
var 市民: [String]
var 資源: [String: Int]
// 發起一個承接城鎮的屬性
// 字串 陣列 字典
init(名字: String, 市民: [String], 資源: [String: Int]) {
self.名字 = 名字
self.市民 = 市民
self.資源 = 資源
}
func 增強防衛() {
print("來!加強防守")
}
}
var 台灣城鎮 = 城鎮(名字: "台灣", 市民: ["蔡英文"], 資源: ["香蕉": 100])
var 美國城鎮 = 城鎮(名字: "美國", 市民: ["拜登"], 資源: ["蘋果": 150])
台灣城鎮.市民.append("馬英九") //城鎮(名字: "台灣", 市民: ["蔡英文", "馬英九"], 資源: ["香蕉": 100])
print(台灣城鎮)
print("-------------")
美國城鎮.增強防衛() //來!加強防守
print(美國城鎮) //城鎮(名字: "美國", 市民: ["拜登"], 資源: ["蘋果": 150])
```

## 編碼練習10
:::success
[編碼練習] 結構
您即將創建下一個大型社交網絡應用程序,專供商業領袖使用,稱為 KingPin。
定義結構
作為此應用程序的一部分,您需要定義一個名為 User 的結構來表示用戶。
這個結構需要保留用戶名、電子郵件(可選)、關注者數量以及他們是否活躍。 User 結構需要具有以下屬性:
姓名
電子郵件?
追隨者
活躍
Struct 還需要有一個名為 logStatus() 的方法。 如果用戶處於活動狀態,則該方法需要打印“XXX 正在努力工作”。 否則,它需要打印“XXX 已離開地球”(其中 XXX 是用戶名)。
初始化結構
定義結構後,創建一個名為“Richard”的用戶,其中有 0 個不活躍的關注者。 然後使用 logStatus() 將此用戶的狀態打印到控制台。
要成功應對這一挑戰,控制台將需要讀取:
```swift!
Richard has left earth
Diagnostic code (i.e., Challenge Hint):
Elon is working hard
Contacting Elon on elon@tesla.com ...
Elon has 2001 followers
Elon has left earth
```
:::
```swift!
// Define the User struct here
struct User {
let name: String
let email: String?
let followers: Int
var isActive: Bool
init(name: String, email: String? = nil, followers: Int, isActive: Bool) {
self.name = name
self.email = email
self.followers = followers
self.isActive = isActive
}
func logStatus() {
if isActive == true {
print("\(name) is working hard") //self.name name print same answer
} else {
print("\(name) has left earth")
}
}
}
// Initialise a User struct here
var richard = User(name: "Richard", email: "", followers: 0, isActive: false)
richard.logStatus()
```
# 99. Creating a Question Struct
```swift!
import Foundation
struct Question {
let text: String
let answer: String
init(q: String, a: String) {
text = q
answer = a
}
}
```

```swift=
//
// ViewController.swift
// Quizzler-iOS13
//
// Created by Angela Yu on 12/07/2019.
// Copyright © 2019 The App Brewery. All rights reserved.
//
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueButton: UIButton!
@IBOutlet weak var falseButton: UIButton!
//題目變數
let quiz = [
Question(q: "第一題 4 加 2 等於 6", a: "True"),
Question(q: "第二題 5 減 3 大於 1", a: "True"),
Question(q: "第三題 3 加 8 比 10 小", a: "False"),
]
var questionNumber = 0
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
updateUI() //初始畫面就啟動函式
}
@IBAction func answerButtonPressed(_ sender: UIButton) {
let userAnswer = sender.currentTitle //True, False
let actualQuestion = quiz[questionNumber] //[ , , ,]
let actualAnswer = actualQuestion.answer
if userAnswer == actualAnswer {
print("Right")
} else {
print("Wrong")
}
if questionNumber + 1 < quiz.count {
questionNumber += 1
} else if questionNumber + 1 == quiz.count {
questionNumber = 0
}
updateUI()
}
//建立函式 更換題目
//因為這函式吃不到 IBAction func answerButtonPressed 內的東西,要吃最外面let quiz
func updateUI() {
questionLabel.text = quiz[questionNumber].text
}
}
```

# 100. Giving the User Feedback and working with a ProgressView
```swift!
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var questionLabel: UILabel!
@IBOutlet weak var progressBar: UIProgressView!
@IBOutlet weak var trueButton: UIButton!
@IBOutlet weak var falseButton: UIButton!
//題目變數
let quiz = [
Question(q: "A slug's blood is green.", a: "True"),
Question(q: "Approximately one quarter of human bones are in the feet.", a: "True"),
Question(q: "The total surface area of two human lungs is approximately 70 square metres.", a: "True"),
Question(q: "In West Virginia, USA, if you accidentally hit an animal with your car, you are free to take it home to eat.", a: "True"),
Question(q: "In London, UK, if you happen to die in the House of Parliament, you are technically entitled to a state funeral, because the building is considered too sacred a place.", a: "False"),
Question(q: "It is illegal to pee in the Ocean in Portugal.", a: "True"),
Question(q: "You can lead a cow down stairs but not up stairs.", a: "False"),
Question(q: "Google was originally called 'Backrub'.", a: "True"),
Question(q: "Buzz Aldrin's mother's maiden name was 'Moon'.", a: "True"),
Question(q: "The loudest sound produced by any animal is 188 decibels. That animal is the African Elephant.", a: "False"),
Question(q: "No piece of square dry paper can be folded in half more than 7 times.", a: "False"),
Question(q: "Chocolate affects a dog's heart and nervous system; a few ounces are enough to kill a small dog.", a: "True")
]
var questionNumber = 0
//預設一進入畫面
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
updateUI() //初始畫面就啟動函式
}
//點擊True或False按鈕
@IBAction func answerButtonPressed(_ sender: UIButton) {
let userAnswer = sender.currentTitle //True, False
let actualQuestion = quiz[questionNumber] //[ , , ,]
let actualAnswer = actualQuestion.answer
if userAnswer == actualAnswer {
sender.backgroundColor = UIColor.green
} else {
sender.backgroundColor = UIColor.red
}
if questionNumber + 1 < quiz.count {
questionNumber += 1
} else if questionNumber + 1 == quiz.count {
questionNumber = 0
}
Timer.scheduledTimer(timeInterval: 0.2, target:self, selector: #selector(updateUI), userInfo:nil, repeats: false)
}
//建立函式 更換題目
//因為這函式吃不到 IBAction func answerButtonPressed 內的東西,要吃最外面let quiz
@objc func updateUI() { //改成object c 函式
questionLabel.text = quiz[questionNumber].text
trueButton.backgroundColor = UIColor.clear
falseButton.backgroundColor = UIColor.clear
progressBar.progress = Float(questionNumber + 1) / Float(quiz.count)
}
}
```

# 101. Understand the MVC Design Pattern

MVC
# 102. Implementing MVC and Understanding Parameter Names
# 103.




## 編碼練習11
:::success
[編碼練習] 函數第 3 部分
使用您所了解的關於可以有輸出的函數的知識,創建一個名為 isOdd(n: Int) 的函數。
對於傳遞給函數的任何給定整數,例如
奇數(n:5)
該函數將測試數字是否為奇數。 如果是,那麼它應該輸出 true,否則它應該輸出 false。 這些是布爾值而不是字符串。
注意:您不應編寫任何打印語句。 只有當結果是輸出時,測試才會通過。
提示:您可以使用餘數運算符來檢查是否可以乾淨地劃分某些內容。
https://docs.swift.org/swift-book/LanguageGuide/BasicOperators.html#ID64
在不更改任何現有代碼的情況下,您的函數應該能夠輸出結果。
在這個 Repl.it 中嘗試一些代碼:https://repl.it/@appbrewery/functions-3-exercise#main.swift
:::
```swift!
//Create your function here 👇
func isOdd(n: Int) -> Bool {
if n % 2 == 0 {
return false
} else {
return true
}
}
isOdd(n: 5) //true
```
# 105. [Swift Deep Dive] Immutability
```swift!
struct 城鎮 {
let 名字: String
var 市民: [String]
var 資源: [String: Int]
// 發起一個承接城鎮的屬性
// 字串 陣列 字典
init(名字: String, 市民: [String], 資源: [String: Int]) {
self.名字 = 名字
self.市民 = 市民
self.資源 = 資源
}
func 增強防衛() {
print("來!加強防守")
}
mutating func 收割米() {
資源["米"] = 200 //其實是 self.資源["米"] = 100 因為self不能改 但是mutating讓self變成var
}
}
var 台灣城鎮 = 城鎮(名字: "台灣", 市民: ["蔡英文"], 資源: ["香蕉": 100])
台灣城鎮.市民.append("馬英九") //城鎮(名字: "台灣", 市民: ["蔡英文", "馬英九"], 資源: ["香蕉": 100])
print(台灣城鎮)
台灣城鎮.收割米() //強制改變了struct結構
print(台灣城鎮) //城鎮(名字: "台灣", 市民: ["蔡英文", "馬英九"], 資源: ["香蕉": 100, "米": 200])
```
# 106.
###### tags: `[Udemy IOS Angela Yu]`