<font color="#8A2BE2">[Udemy IOS Angela]</font> Ch8 Control Flow and Optionals === # Ch8 Outline * Project Skeleton * If/Else Statement * Switch Statement * Dictionay * Optionals * UIProgressView track of time * Debug App ## 81. Setting up the Egg Timer Project and Linking the Storyboard and ViewController ![](https://i.imgur.com/UBItsAa.png) ![](https://i.imgur.com/ciyn324.png) 寫法 ![](https://i.imgur.com/c01YZjR.png) Angela解法 ![](https://i.imgur.com/j7sNbCs.png) ![](https://i.imgur.com/JbPFGIF.png) ```swift= print(sender.currentTitle) //Optionals + 文字 print(sender.currentTitle!) //抓點擊的文字 print(sender.titleLabel!.text!) //抓文字 ``` ### 點擊蛋,分別印出不同時間 ![](https://i.imgur.com/4Fa9n3h.png) ## 82. IF/ELSE ```swift= if trafficLight == "green" { go() } else if trafficLight == "amber" { useYourJudegement() } else { stop() } ``` ### 相愛一輩子vs孤單一輩子 ```swift= //建立函式loveCalculator //隨機生成數字 //存成一個loverScore變數 //如果變數是100 印出 相親相愛 //不然就印出 孤單一輩子 func loveCalculator(){ let loverScore = Int.random(in: 0...100) if(loverScore == 100) { print("\(loverScore)相愛一輩子") } else { print("\(loverScore)孤單一輩子") } } loveCalculator() loveCalculator() loveCalculator() loveCalculator() ``` ![](https://i.imgur.com/ndKDYrK.png) ```swift= * == 等於 * != 不等於 * > 大於 * < 小於 * >= 大於等於 * <= 小於等於 && AND || OR ! NOT ``` ### 相愛一輩子vs相愛一下子vs孤單一輩子 ```swift= //建立函式loveCalculator //隨機生成數字 //存成一個loverScore變數 //如果變數是100 印出 相親相愛 //不然就印出 孤單一輩子 func loveCalculator(){ let loverScore = Int.random(in: 0...100) if(loverScore >= 80) { print("\(loverScore)相愛一輩子") } else if(loverScore >= 40 && loverScore <= 80) { print("\(loverScore)相愛一下子") }else { print("\(loverScore)孤單一輩子") } } loveCalculator() loveCalculator() loveCalculator() loveCalculator() ``` ![](https://i.imgur.com/6HWubGi.png) ### 編碼練習 6: [Coding Exercise] IF/ELSE 閏年/平年 ```swift= /* 每四年一個閏年,該年會多1天,366天 閏年3個條件 條件1. 年份可以被四整除(沒有提示)則為閏年,除非: 條件2. 如果年份也可以被 100 整除(以兩個零結尾的年份),那麼它不是閏年,除非 條件3. 它也可以被 400 整除(在這種情況下它將是閏年)。 1997 年不是閏年, 1996 年是 1900 年不是閏年 被4整除,年份被100整除,所以不是 2000 年是。 被4整除,年份被100整除,滿足年份被被400整除 */ //Don't change this var aYear = Int(readLine()!)! //互動,等待使用者輸入年份 func isLeap(year: Int) { //Write your code inside this function. //isLeap(year: aYear) //year is the parenthesise name //aYear is the value if( (year % 4 ) != 0 ) { print("No") } if( year % 4 == 0 && year % 100 == 0 && year % 400 == 0) { //1200will be in this line print YES print("YES") } else if( year % 4 == 0 && year % 100 == 0 ) { print("NO") } else if( year % 4 == 0 ) { print("YES") } } //Try out your function with some different years. Don't copy the line below (it's not part of the exercise you need to complete). isLeap(year: aYear) ``` ![](https://i.imgur.com/FlB1VJ3.png) ## 83. [Swift Deep Dive] Switch Statements ```swift= 當案例很多Switch 就很好用 switch hardness { case "Soft": print(5) case "Medium" print(7) case "Hard": print(12) default: print("Error") } ``` ```swift= a...b 介於a到b之間 a..<b 介於a到b-1之間 ...b 任何小於b的數字 ``` :::info switch判斷語法 + switch改成布林判斷 ```swift= func loveCalculator() { let loverScore = Int.random(in: 0...100) switch true { case loverScore>=80: print("\(loverScore)相愛一輩子") case (loverScore>=40&&loverScore<=80): print("\(loverScore)相愛一下子") case (loverScore<=40): print("\(loverScore)孤單一輩子") default: print("輸入不存在我的判斷") } } loveCalculator() loveCalculator() loveCalculator() loveCalculator() ``` ![](https://i.imgur.com/tZmUVTI.png) 圖片需修正,依據程式碼為主(81...100 41...80) ::: :::danger switch判斷語法 + a...b介於數字寫法 ```swift= func loveCalculator() { let loverScore = Int.random(in: 0...100) switch loverScore { case 81...100: print("\(loverScore)相愛一輩子") case 41..<80: print("\(loverScore)相愛一下子") case ...40: print("\(loverScore)孤單一輩子") default: print("輸入不存在我的判斷") } } loveCalculator() loveCalculator() loveCalculator() loveCalculator() ``` ![](https://i.imgur.com/hUupGOz.png) 圖片需修正,依據程式碼為主(81...100 41...80) ::: ### 編碼練習 7: [Coding Exercise] Switch ```swift= [編碼練習] 開關 創建一個程序,將數字 (Int) 作為輸入並使用 Switch 語句打印相應的星期幾。 例如如果輸入是 5 然後函數應該打印: “星期五” 如果輸入的數字與星期幾不匹配,那麼您的程序應該打印“錯誤”。 您可以在此處試用您的代碼:https://repl.it/@appbrewery/switch-exercise#main.swift 提示:打印的工作日需要首字母大寫且拼寫正確才能通過測試。 ``` ```swift= ////Don't change this var aNumber = Int(readLine()!)! func dayOfTheWeek(day: Int) { //Write your code inside this function. switch day { case 1 : print("Monday") case 2 : print("Tuesday") case 3 : print("Wednesday") case 4 : print("Thursday") case 5 : print("Friday") case 6 : print("Saturday") case 7 : print("Sunday") default: print("Error") } } dayOfTheWeek(day: aNumber) ``` ![](https://i.imgur.com/5viXmFd.png) ![](https://i.imgur.com/P10CjgE.png) ![](https://i.imgur.com/wixpovI.png) [參考](https://www.udemy.com/course/ios-13-app-development-bootcamp/learn/quiz/5037444#questions/13786852) ## 84. Conditional Statements Challenge Solution ```swift= import UIKit class ViewController: UIViewController { let softTime = 5 let mediumTime = 7 let hardTime = 12 //挑戰1 //建立一個按鈕hardnessSelected IBAction //連接到3個蛋 //按下蛋會印出Soft Medium Hard字樣 @IBAction func hardnessSelected(_ sender: UIButton) { //print(sender.currentTitle!) //抓點擊的文字 let hardness = sender.currentTitle //把點擊文字變成一個變數 //挑戰2 //點擊Soft 印出5 ; Medium 印出7 ; Hard 印出12 if(hardness == "Soft"){ print("\(softTime)") }else if(hardness == "Medium"){ print("\(mediumTime)") }else if(hardness == "Hard"){ print("\(hardTime)") } } } ``` ![](https://i.imgur.com/aptMYxa.png) ## 85. [Swift Deep Dive] Dictionaries ```swift= key value var dict = ["Brewery" : "a place where beer is made", "Bakery" : "a place where bread is made"] key字串 value整數 var dict : [String : Int] = ["Angela" :7712345678, "Philipp" : 7787654321] dict["Angela"] //印出7712345678 ``` ### 編碼練習 8: [Coding Exercise] Dictionaries ```swift= [編碼練習] 字典 添加新條目 Slack Technologies Inc 是 Slack 背後的公司, Slack 是流行的消息傳遞和協作工具,最近於 2019 年 4 月首次公開募股。 它在紐約證券交易所上市,股票代碼為 WORK。 使用鍵“WORK”和值“Slack Technologies Inc” 向 stockTickers 字典添加一個條目。 更新現有值 Dynamic Materials Corp 是一家專門從事爆炸金屬加工 (如熔覆或衝擊硬化)的公司。但是, 公司的正式名稱不是“Dynamic Materials”, 而是“DMC Global Inc”。將股票代碼 BOOM 的值更新為“DMC Global Inc”。 ``` ```swift= func exercise() { //Don't change this var stockTickers: [String: String] = [ "APPL" : "Apple Inc", "HOG": "Harley-Davidson Inc", "BOOM": "Dynamic Materials", "HEINY": "Heineken", "BEN": "Franklin Resources Inc" ] //Write your code here. stockTickers["WORK"] = "Slack Technologies Inc" //添加字典內容 stockTickers["BOOM"] = "DMC Global Inc" //修改既有字典內容 //Don't modify this print(stockTickers["WORK"]!) print(stockTickers["BOOM"]!) } exercise() ``` [參考](https://www.tutorialkart.com/swift-tutorial/swift-dictionary-append-element/) ## 86. [Swift Deep Dive] Defining and Unwrapping Optionals :::danger optional就像是箱子內貓與毒藥放在一起,你不知道裡面貓是活的還是死的 nil 裡面的貓死了 ::: ```swift= var hardness :String? //變數hardness 資料類別是字串,目前值可以是『有東西』或是『空值』都行 var player1Username: String = nil //建立變數報錯 var player1Username: String? = nil //建立變數可以執行 player1Username = "AngelaIsAwesome" //變數賦值 print(player1Username) //印出 Optional("AngelaIsAwesome") print(player1Username!) //印出 AngelaIsAwesome //!就像是安全檢查,防止我們在嘗試用空值去做事情讓程式崩潰 var unwrappedP1Username = player1Username! //建立新變數,把Optional("AngelaIsAwesome") 賦值給新變數 player1Username = nil //把原本值刪除,設定為空 print(player1Username) //player1Username是空nil print(player1Username!) //報錯,會通知,這樣印有可能會印出空 //建議用if來保護 if player1Username != nil { //如果不是空,會印東西,是空,就不會印 print(player1Username!) } ``` ### 編碼練習 9: [Coding Exercise] Optionals ```swift= [編碼練習] 可選 如果你有一本字典,裡面有 3 個學生的名字和他們的考試成績,你能打印出最高分嗎? 例如如果 studentsAndscores = [“艾米”:88,“詹姆斯”:55,“海倫”:99] 然後你的函數應該打印 99。 但是你不知道分數是多少,所以你的程序必須處理所有的可能性! 提示:當你使用鍵從字典中取出值時,出來的值是可選的! 請務必使用示例輸入測試您的代碼,並在此處試用您的代碼:https://repl.it/@appbrewery/optionals-exercise#main.swift ``` ```swift= //Don't change this var studentsAndScores = ["Amy": Int(readLine()!)!, "James": Int(readLine()!)!, "Helen": Int(readLine()!)!] func highestScore(scores: [String: Int]) { //建立一個函式 //Write your code here. //print(scores) //會印出全部參數的值 //print(studentsAndScores.values.max()) //Optional(92) print(studentsAndScores.values.max()!) } //Try some different scores. //Dont add the lines below to udemy! highestScore( //呼叫函式 scores: ["Amy": 78, "James": 65, "Helen": 92] ) ``` ![](https://i.imgur.com/flWbH9l.png) ![](https://i.imgur.com/HUiNlLE.png) [參考字典找最大值](https://stackoverflow.com/questions/72731141/print-the-key-of-the-max-value-from-a-dictionary-swift) ## 87. Dictionary Challenge Solution print 加上驚嘆號 ![](https://i.imgur.com/Bt3O1v2.png) ![](https://i.imgur.com/GJKb1SQ.png) ## 88. Implementing a Countdown Timer Challenge 建立一個時間倒數器 ```swift= class ViewController: UIViewController { var secondsRemaining = 30 @IBAction func startTimer(_ sender: UIButton) { Timer.scheduledTimer(withTimeInterval: 1.0, repeats: true) { (Timer) in if self.secondsRemaining > 0 { print ("\(self.secondsRemaining) seconds") self.secondsRemaining -= 1 } else { Timer.invalidate() } } } ``` ![](https://i.imgur.com/jbrrPis.png) [參考](https://stackoverflow.com/questions/29374553/how-can-i-make-a-countdown-with-nstimer) Angela版本 ```swift= import UIKit class ViewController: UIViewController { //使用字典資料結構 let eggTimes = ["Soft": 300, "Medium": 420, "Hard": 720] var secondsRemaining = 60 @IBAction func hardnessSelected(_ sender: UIButton) { let hardness = sender.currentTitle! //把點擊文字變成一個變數 secondsRemaining = eggTimes[hardness]! //倒數秒數依據點擊蛋秒數不同 //倒數libary 間隔1秒 Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) } //Object C libary @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 } } } ``` :::danger 這程式有個問題,當點擊Soft圖,又再點擊Medium圖,又再點擊Hard圖 一秒會跑3個second 原因 17行Timer.scheduledTimer()並未真正取消,每點擊一個蛋會執行17行,而且又會呼叫21行@objc func updateTimer() 當一直點擊每秒倒數數度會越增越多,速度越來越快 ::: ![](https://i.imgur.com/PjPTYha.png) ## 89. Egg Timer Challenge Solution ```swift= import UIKit class ViewController: UIViewController { let eggTimes = ["Soft": 300, "Medium": 420, "Hard": 720] var secondsRemaining = 60 var timer = Timer() //建立一個時間變數 @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() //每次點擊之前的變數變成無效 let hardness = sender.currentTitle! //把點擊文字變成一個變數 secondsRemaining = eggTimes[hardness]! //把計時libary設為一個變數 timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) } @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 } } } ``` ### 秒數倒數完,畫面文字改變 修改處 ```swift= @IBOutlet weak var eggText: UILabel! @objc func updateTimer() { if(secondsRemaining == 0) { self.eggText.text = "Done" } } ``` 參考StackOverflow ```swift= import UIKit class ViewController: UIViewController { let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] var secondsRemaining = 60 var timer = Timer() @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! //把點擊文字變成一個變數 secondsRemaining = eggTimes[hardness]! timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) } 把文字拉成程式 @IBOutlet weak var eggText: UILabel! @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 當0秒時 if(secondsRemaining == 0) { self.eggText.text = "Done" } } } } ``` ![](https://i.imgur.com/Zh0U7cI.png) ![](https://i.imgur.com/NLt4bCr.png) [參考](https://stackoverflow.com/questions/24275632/how-do-i-change-text-in-a-label-with-swift) Angela ```swift= //標籤拉成程式碼 @IBOutlet weak var eggText: UILabel! else { timer.invalidate() //時間暫停 eggText.text = "Done" //文字顯示完成 } ``` ```swift= import UIKit class ViewController: UIViewController { let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] var secondsRemaining = 60 var timer = Timer() @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! //把點擊文字變成一個變數 secondsRemaining = eggTimes[hardness]! timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) } //標籤拉成程式碼 @IBOutlet weak var eggText: UILabel! @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 } else { timer.invalidate() //時間暫停,不再計時 eggText.text = "Done" //文字顯示完成 } } } ``` ## 90. Showing the Timer to the User with a Progress View ![](https://i.imgur.com/KnhZeFH.png) ![](https://i.imgur.com/pAk4wVo.png) ![](https://i.imgur.com/zRilf3S.png) ![](https://i.imgur.com/GCyXikn.png) 0.5代表剩下1/2 ![](https://i.imgur.com/2NPt8Ws.png) 0.1代表勝下1/10 ![](https://i.imgur.com/QqtiRiR.png) ### 點擊一次,進度條直接變成100% 新加入 ```swift= @IBOutlet weak var progressView: UIProgressView! progressView.progress = 1 ``` 全部code ```swift= import UIKit class ViewController: UIViewController { let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] var secondsRemaining = 60 var timer = Timer() @IBOutlet weak var progressbar: UIView! @IBOutlet weak var progressView: UIProgressView! @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! //把點擊文字變成一個變數 secondsRemaining = eggTimes[hardness]! timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) print(progressbar!) progressView.progress = 1 } //標籤拉成程式碼 @IBOutlet weak var eggText: UILabel! @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 } else { timer.invalidate() //時間暫停 eggText.text = "Done" //文字顯示完成 } //else if{progressBar.progress == Float } } } ``` ![](https://i.imgur.com/ejM7eeJ.png) [參考](https://stackoverflow.com/questions/31432777/swift-creating-a-progress-bar) Angela ```swift= import UIKit class ViewController: UIViewController { @IBOutlet weak var progressBar: UIProgressView! @IBOutlet weak var titleLabel: UILabel! let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] var secondsRemaining = 60 var timer = Timer() @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! secondsRemaining = eggTimes[hardness]! timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) progressBar.progress = 1 } @objc func updateTimer() { if secondsRemaining > 0 { print ("\(secondsRemaining) seconds") secondsRemaining -= 1 } else { timer.invalidate() //時間暫停 titleLabel.text = "Done" //文字顯示完成 } } } ``` ![](https://i.imgur.com/a4W4tHg.png) ## 91. Calculating the Progress Percentage 讓進度條顯示剩餘的時間 progress 0 -> 1 (秒數/100逐次加總) secondsRemaining = progress.text * 顯示百分比 56% = 0.56 * 不同蛋不同秒數 soft egg 300秒/hard egg 720秒 走過秒數/總時間=進度百分比 * updateTime函式每秒做一個動作 執行,點擊蛋,進度條直接下降0卻沒有動作 ```swift= import UIKit class ViewController: UIViewController { @IBOutlet weak var progressBar: UIProgressView! @IBOutlet weak var titleLabel: UILabel! let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] //var secondsRemaining = 60 var timer = Timer() var totalTime = 0 //總時間 var secondPassed = 0 //起始時間 @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! totalTime = eggTimes[hardness]! timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) //progressBar.progress = 1.0 } @objc func updateTimer() { if secondPassed < totalTime { let percentageProgress = secondPassed / totalTime //走過秒數/總時間=進度百分比 progressBar.progress = Float(percentageProgress) //progress是浮點數0.1這種數字 secondPassed += 1 } else { timer.invalidate() //時間暫停 titleLabel.text = "Done" //文字顯示完成 } } } ``` ![](https://i.imgur.com/GpnaQ3H.png) ## 92. Using the 5 Step Approach to Debug our App ```swift= 各自變成浮點數,再除才會得到2.5這樣小數,不然都會是2.0 let a = 5 let b = 2 print(a / b) //2 print(Float(a / b)) //2.0 print(Float(a) / Float(b)) //2.5 ``` ```swift= import UIKit import AVFoundation //匯入音檔 class ViewController: UIViewController { var player: AVAudioPlayer! //建立音檔變數 @IBOutlet weak var progressBar: UIProgressView! @IBOutlet weak var titleLabel: UILabel! let eggTimes = ["Soft": 3, "Medium": 4, "Hard": 7] //var secondsRemaining = 60 var timer = Timer() var totalTime = 0 var secondPassed = 0 @IBAction func hardnessSelected(_ sender: UIButton) { timer.invalidate() let hardness = sender.currentTitle! //變數hardness就是我們點擊的東西名稱 totalTime = eggTimes[hardness]! progressBar.progress = 0.0 secondPassed = 0 titleLabel.text = hardness timer = Timer.scheduledTimer(timeInterval: 1.0, target:self, selector: #selector(updateTimer), userInfo:nil, repeats: true) playSound() } //音樂函式(參考之前音樂範例檔案) func playSound() { let url = Bundle.main.url(forResource: "alarm_sound", withExtension: "mp3") player = try! AVAudioPlayer(contentsOf: url!) player.play() } @objc func updateTimer() { if secondPassed < totalTime { secondPassed += 1 //先加再計算百分比 progressBar.progress = Float(secondPassed) / Float(totalTime) print(Float(secondPassed) / Float(totalTime)) } else { timer.invalidate() //時間暫停 titleLabel.text = "Done" //文字顯示完成 } } } ``` ![](https://i.imgur.com/9Q1xhxN.png) ###### tags: `[Udemy IOS Angela Yu]`