---
# System prepended metadata

title: '技術-iOS #7-伸出觸角呼叫 api，存取 GPS，連同 delegate 等技術'
tags: [新人資訊]

---

---
tags: 新人資訊
GA: G-YWCCFEGXSJ
---
[新人資訊](https://hackmd.io/@newman/portal-info)

# 技術-iOS #7-伸出觸角呼叫 api，存取 GPS，連同 delegate 等技術

本回合所要完成的應用是，取得所在位置資訊，或輸入全球任一個城市的名稱，然後程式透過網路呼叫 openweathermap 提供的 api 取得當時天氣，顯示在 app 畫面上。此單元學到超多東西，如讓 app 可以切換深色模式/淺色模式，protocol (幾乎等同於 interface)，delegate design pattern，closure (類似匿名函數)，extension，呼叫 api，解析 json 物件，最後連 GPS 抓位置的方法也搞定了，真是太大包了，學得太過癮了，先下載專案框架：https://github.com/appbrewery/Clima-iOS13 稍微看一下 UI 佈局。

![](https://newprediction.blob.core.windows.net/notebook-img/JRcxsD7.png)

首先登場的名詞是 protocol，聽了好久後來才發現其實是原來所慣用的 interface；一般的 protocol 是沒有任何實作的，只規定必須實作的方法規格，但此專案使用到系統內建的 protocol 時卻發現不實作也不會有錯誤，這令我困惑很久！後來才發現原來 protocol 可以透過 extension 去定義預設的實作！extension 功能非常強大，也可以用在延伸既有的 class or struct。

另一個名詞為 closure，剛聽時真是一頭霧水，原來就是一個「匿名函數」，不同於習慣的 lumbda 語法，變成怪怪的一整個不習慣，在此筆記一下：https://docs.swift.org/swift-book/LanguageGuide/Closures.html 相信 apple 的設計水準，應該很快就會習慣。

![](https://newprediction.blob.core.windows.net/notebook-img/156yXMB.png)

然後一個重要的觀念 delegate design pattern 登場，這個已經融入各語言的基本組成了，雖然以前用過，但都是胡亂 google 依樣葫蘆，總覺得觀念似懂非懂，這次認真跟著講師重頭開始手把手一邊實作一邊娓娓道來，真的非常受用，再用自己的話筆記下來，希望觀念可以印的更深刻，如以下的例子：

「急救支援服務」是一個 protocal，其中規定必須實作一個方法 performCPR()
「勤務中心」是一個 class，裡面有一個欄位稱為 delegate，其型別為「急救支援服務」；另外有許多任務需要執行，其中有用到 CPR 的部分直接呼叫 delegate?.performCPR()，此時並不知道何種實體會執行此動作，但可確保不管任何實體都必須實作「急救支援服務」，因此保證有 performCPR() 這個方法。我想成把急救支援服務外包 (委派) 的意思。
「護理師」是一個 struct，它實作「急救支援服務」這個 protocal，所以它必須實作 performCPR()，而妙的是在護理師的建構子中規定必須傳入參數「勤務中心」也就是護理師依存於一個勤務中心，而把勤務中心裡面的 delegate 設成自己！這就是奇妙的有點詭異的地方！對比於護理師，可以建立另一個 struct「醫師」擔任同要角色。
以上為設計和定義的部分，下面開始引用之讓系統運作起來：
「台北醫療服務站」是一個勤務中心的實體，「Mary」是一個護理師，當護理師被初始化時傳入「台北醫療服務站」，根據護理師 class 的定義，會把醫療服務站的 delegate 設成自己，此情境可用一句話描述：Mary 護理師到台北醫療服務站上工執勤。依此類推，另一個情境可能是：Peter 醫師到台北醫療服務站執勤。對台北醫療服務站而言只管執行日常勤務，其中 performCPR() 是由誰執行它可以不在意，但可保證有人執行，醫療服務站的運作機制也可以重複運用。以上，覺得講師還講得真好。

delegation design pattern 應與到此 app 的用法，體現在關於那個輸入城市名稱的 searchTextField 的驗證處理機制。「驗證機制」在這兒是 UITextFieldDelegate，是一個 protocol，規定必須實作 ShouldReturn, ShouldEndEditing, DidEndEditing 等方法，相當於上述的急救支援服務，這個 ViewController 引用此 protocol 就是使自己成為受訓認證而有驗證能力的專業人士，在他自己初始化時就與它的服務對象 searchTextField 建立關聯成為它裡面的 delegate 欄位，當服務對象需要時 (使用這按下搜尋鍵停止編輯時，或按下虛擬鍵盤 enter 鍵時) 透過 delegate 欄位呼叫執行驗證機制和後續取得天氣資訊的程序。(好拗口，也好漂亮)

![](https://newprediction.blob.core.windows.net/notebook-img/YN4UwEH.png)

delegate design pattern 二度使用於「顯示天氣資訊」，包含更新一個圖示和顯示溫度和城市名稱。顯示天氣資訊這種事情需要事先執行耗時的網路傳輸 api 呼叫和 decode JSON 等動作，所以無法由顯示方 (也就是畫面) 主導，所以我們另外建立一個 struct WeatherManager 來主導執行細節，執行完成再「委任」非特定對象執行顯示工作，所以此畫面的 viewController 就是需要引用 protocol 的人，而定義 protocol 則在 WearherManager 裏面：

![](https://newprediction.blob.core.windows.net/notebook-img/9GpKyrK.png)

注意到以上 session.dataTask() 後面就是 closure，多看幾次語法也快就習慣了。而 ViewController 部分引用了 extension 功能，不用把一堆程式寫在同一個 class 裡面，而是「擴充」之寫在另一個區塊，這樣的結構看起來非常清晰美觀。

![](https://newprediction.blob.core.windows.net/notebook-img/po8yA5I.png)

關於解析 JSON 的細節，必須觀察 api 回傳的結構，挑出想要的欄位，完全仿照其結構建立一個 struct 如下 WeatherData，若有巢狀結構也必需比照辦理。conditionName 則不在 api 回傳欄位之內，我們自己用 getConditionName() 取得對應 swift 內建的 icon name，要傳回畫面端顯示雲或太陽等圖樣。

![](https://newprediction.blob.core.windows.net/notebook-img/iWpYSXy.png)

![](https://newprediction.blob.core.windows.net/notebook-img/lqDaEMD.png)

最後還有一個任務，就是抓到 GPS 資訊定位到及時的經緯度！預計在畫面載入之後隨即啟動模組取得位置，之後也可以在畫面點選按鈕再次執行此程序。

![](https://newprediction.blob.core.windows.net/notebook-img/6lZg5Cp.png)

與 WeatherManager 完全一樣的作法，再玩一次 delegate，再次 extent ViewController，把自己註冊給 locationManager，在 locationManager 完成定位任務就會透過 delegate 觸發 locationManager(_, didUpdateLocation)，在此 _ 代表呼叫方不需指定參數名稱，didUpdateLocation 是 external parameter name，locations 為 inner parameter name，這些都可透過查詢文件得知，寫法很靈活，存在一堆眉角，用慣了應該會很方便。 取得經緯度後就傳給 weatherManager 繼續取得即時天氣的程序。

![](https://newprediction.blob.core.windows.net/notebook-img/jm186jb.png)

以上終於完成全部拼圖，執行起來如下，簡單幾個動作背後的技術含量真不少啊！

https://youtu.be/-KmyLBNmrWI

By Newman Chen 2022/7/21

