#筆記 串接 API:POST 請求 & 解析日期 — SwiftUI 新手入門 6–6

Dong
10 min readAug 24, 2023

--

題目及內容取自於 : ChaoCode 頻道

網址連結:

筆記:

> 串接API: 新增最愛項目

> 讓 stub 根據 endPoint 回傳不同資料

> 處理網路狀態碼錯誤

> 串接 API : 讀取最愛項目

> 解析日期

> 修改: 將 CatImageViewModel 改為剛剛建立的 FavoriteResponse

> 串接 API : 刪除最愛項目

> 最終畫面

串接API: 新增最愛項目 -

先查看文件說明,確認 POST 需要哪些項目,以及驗證要求

新增最愛項目的文件說明
驗證機制文件說明

API Key 取得方式: 網址

至自己填寫的郵箱取得 key

接著建立 addFavorite(),根據文件說明放入需要的資料

FavoriteCreationResponse 用來 Decode (Request 回傳回來的 data)

讓 stub 根據 endPoint 回傳不同資料 -

接著在 Test 中新增測試 addFavorite 是否正確執行,但目前的 stub 都是回傳一樣的資料,跟前面介紹新增最愛項目的回傳結果不一樣,因此這邊要修改成根據 endPoint 回傳不同的內容,才能使 addFavorite 的測試正確。

在 CatAPIManager 中,用 Enum 建立 EndPoint

( 圖片跟最愛項目2個 case )

用 Enum 建立 EndPoint

新增一個新檔案管理 EndPoint ,並建立 stub ,根據 case 回傳不同資料

皆是固定的資料,拿來做測試使用

接著在 EndPoint 建立 request 屬性,將原先的網路呼叫 function 做調整,根據不同 case 有不一樣的 URLRequest,再更改取得 Data 的方式

修改調整之前的 Code

shared ( URLRequest ) 、 stub ( 固定資料 ) 裡面各自針對 .image 跟 addToFavorite 都有個別的回傳

示意圖

接著到 Test ,檢查 addToFavorite 是否回傳正確的值

回傳 stub 裡面 addToFavorite 的值做檢查

最後回到主畫面修改呼叫API的地方

將 error 向外拋,並加上 async
有用到的地方加上 try await / async throws
先用 ! 強制解開,並用 Task 包起來,後續再處理 ERROR

處理網路狀態碼錯誤 -

將目前的 Code 燒入至模擬器中,在貓咪圖片上點擊2下(加到最愛項目)會跳出 Error,

點擊後會跳出 Error
可以看到錯誤狀態碼(400)
網路狀態碼 400 — 有可能是請求格式錯誤或包含無效資料等等

於是到拋出這段 Error 的地方,加上 assertionFailure()

報錯之前會先停在這一行,方便 debug 裡面的內容

接著再次燒入至模擬器點擊圖片

報錯停止在 assertionFailure 這行

這時可以在下方的 console 輸入程式碼,可以讀取一些資料

console 輸入程式碼 po + ( ) ,可以獲取一些資料
可以將 String(data: data, encoding: .utf8) 移至 assertionFailure() 中,報錯時會顯示下面那段內容

接著回到 CatAPIManager 中,實際錯誤的原因是沒有在 Header 的 Content — Type 中告知是 Json 類型

必須在 Header 的 Content- type 欄位中,告知資料類型

補充:

網路狀態碼

資料類型

串接 API : 讀取最愛項目 -

跟上面一樣透過一個 EndPoint 去取得 Data

這邊先不管使用者 id,跟 page (最愛項目太多時,需要呼叫下一頁)

更改調整之前的 Code

在 CatAPIManager 建立一個 helper function
透過上面建立的 fetch ,來取得資料

接著在 EndPoint 建立 .favorites 的 case

先不處理 page
.stub 中的假資料,用文件說明說的範例

創建一個 FavoriteResponse 的 Model 來處理最愛項目的資料,

自己寫解碼方式: 網址

而在新增、刪除 favorites 也會需要用到 APIkey ,所以將 key 改至 session 中

( header 可以在 session 中,透過 configuration 統一設定)

URLSession 、 URLSessionConfiguration 介紹: 網址

最後就可以建立 function 來 getFavorites 資料

回傳 FavoritesResponse 的 Array

解析日期-

這邊我們至 Test 中,測試 stub 中的 imageURL 是否取得正確,點下測試後,在 console 中可以看到執行失敗的資訊

在 Decode 過程中,預期是要解碼 Double 類型的資料,卻是 string / data 的類型

這是因為解碼過程中,日期(Date)的解碼,不是預期的類型導致( Type mismatch )

Unix Timestamp 為 1970/01/01 至今的總秒數(時間表示的一種)

在這邊可以對於 decoder 做一些調整

在 fetch 的 function 中,對 decoder 做調整

回到 Test ,再執行一次就能夠成功 Decode 了

日期成功解析

修改: 將 CatImageViewModel 改為剛剛建立的 FavoriteResponse -

將原先的 CatImageViewModel 改為使用剛才建立的 FavoriteResponse

FavoriteResponse 名稱改成 FavoriteItem,並放進新建的資料夾中
將原先有些呼叫 CatImageViewModel 的地方 ,換成 FavoriteItem

因為變為 FavoriteItem ,下面這些原本取得圖片的 \.id 改為 \.imageID

再把 \.id 改為 \.imageID,來取得圖片

接著在 add (新增至我的最愛項目中) 裡,需要是 FavoriteItem ,所以新增一個 CatImageViewModel 啟動方法

新增一個用 CatImageViewModel 啟動的方法

建立好後,回到 add 中做修改

用上面建立的啟動方式,搭配 append 加到 favorite 中
Preview 也順便修改

此時會跳出一個 Error ,說類型錯誤

所以到 CatImageViewModel 中,新增一個 FavoriteItem 的啟動方法 (與上面剛好相反 ( CatImageViewModel ↔ FavoriteItem )

新增一個 FavoriteItem 的啟動方法
回到 screen,修改呼叫
並把 id 改成 imageID

這時候還是有個 Error,告訴我們 .animation 動畫追蹤的 value 必須 conforms to Equatable,才能知道 value 有沒有變化,作為變化是否更新的依據,所以幫 Favorite 添加遵從 Equatable 這個 Protocol

Equatable 文件說明 - 網址

串接 API : 刪除最愛項目 -

會需要在 apiManager 、網路端刪除,先將 addremove 這兩個 Function ,放到 [FavoriteItem] 的 extension 中,最後要做到呼叫 .remove 時,兩個都被刪除

接著先做設備上的刪除

extension 改為 [FavoriteItem],並把 private 刪掉,外部才能呼叫
直接使用 .add / .remove

再來做呼叫網路端的刪除

CatImageAPI 刪除的文件說明

先新增 刪除的 EndPoint

需要給 id ,不能用之前新增的 URL 啟動方式,httpMethod 要改為 DETELE
stub 中,讓 case 回傳一個空的 string 才不會報錯

再建立 Function ,向伺服器發出刪除的請求

這邊的 DELETE 不會回傳任何資料 , 所以不用透過 fetch

最後回到 [FavoriteItem] extension 中的 .remove ,呼叫剛剛在 APIManager 中建立的 removeFromFavorite

可以從 self[index].id 取得ID

最終畫面 -

這集完成時的畫面

可以看出以下缺點: (下一集處理)

  • 載入 / 重整 : 載入畫面不流暢
  • 新增 : 點擊 2 下,愛心出現有延遲
  • 刪除 : 移除最愛項目時也有延遲

--

--