模仿 Apple 官方範例串接 REST API 的 5 種寫法
開發 iOS App 時,我們時常需要串接 REST API 抓取網路上的資料。當串接的 API 一多時,採用好的寫法才能讓程式容易維護和修改。
以下我們將模仿 Apple 官方範例,示範串接 REST API 的 5 種寫法。
- 方法1: 定義串接 API 的物件, 搭配 async function。
ex: 在 class CatApiClient 裡定義 func fetchFavorites() async throws -> [Favorite]
- 方法2: 定義串接 API 的物件,串接 API 的 function 裡定義 function 型別的 completion 參數 & 使用 Result type
若是時間有限,建議先研究此方法,因此它較易學習,而且也算初學者常採用的方法。若想支援舊版可採用此寫法
ex: 在 class CatApiClient 裡定義 fetchFavorites(completion: @escaping (Result<[Favorite], Error>) -> Void)
- 方法3: 定義串接 API 的物件,串接 API 的 function 裡定義 function 型別的 completion 參數
在 Result type 發明之前常用的方法。
ex: 在 class CatApiClient 裡定義 func fetchFavorites(completion: @escaping ([Favorite]?) -> Void)
- 方法4: 使用 generic,protocol & associatedtype 定義 APIRequest & APIService,搭配 async & await
較佳的寫法,許多程式可重覆利用,之後新增 API 時要撰寫的程式較少。
ex: 每個 API 定義對應的 request。
struct UpdateVoteRequest: APIRequest {
var path = "/votes"
let updateVoteBody: UpdateVoteBody
var method: HTTPMethod { .post }
typealias Response = UpdateVote
var data: Data? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return try? encoder.encode(updateVoteBody)
}
}
參考 Apple 的 Develop in Swift Data Collections 第三章 Guided Project: Habits。
- 方法5: 使用 generic,protocol & associatedtype 定義 APIRequest & APIService,搭配 Result type
較佳的寫法,許多程式可重覆利用,之後新增 API 時要撰寫的程式較少。若想支援舊版可採用此寫法。
ex: 每個 API 定義對應的 request。
struct UpdateVoteRequest: APIRequest {
var path = "/votes"
let updateVoteBody: UpdateVoteBody
var method: HTTPMethod { .post }
typealias Response = UpdateVote
var data: Data? {
let encoder = JSONEncoder()
encoder.keyEncodingStrategy = .convertToSnakeCase
return try? encoder.encode(updateVoteBody)
}
}
請 AI 依據範例和 API 文件開發串接 API 的 Swift 程式
串接的 API 範例
以可愛喵喵的 The CAT API 為例。
我們將示範以下 3 個 API。
- 抓取使用者的最愛喵喵清單(favorite, GET)。
- 幫喵喵圖片的可愛分數增加一分。(vote up, POST JSON)
- 上傳喵喵圖片。(POST multipart/form-data)
由於以上三個功能都需要 API key,因此請參考以下連結申請 API key,或是使用 Demo 的 API key DEMO-API-KEY
。
App 畫面
從第一頁的 table 選擇串接 API 的方法,第二頁將抓取最愛喵喵清單顯示在 table 上,點選右上的 + 會幫喵喵圖片的可愛分數增加一分,點選右上的照片按鈕會上傳圖片。
範例專案連結
storyboard 畫面
專案架構 & 說明
- 5 種方法的畫面依序對應 5 個 view controller。
- 假設登入的使用者 id 是 123。
struct User {
let id: String
static var current: User? = User(id: "123")
}
- 串接 API 的程式定義在 service 下。
以 method1 ~ 5 區分不同的方法。
method 4 & 5 的差別在 APIRequest 的 send function。method 4 定義 func send() async throws -> Response
,method 5 定義 func send(completion: @escaping (Result<Response, Error>) -> Void)
。
- API 失敗時也會回傳 JSON,對應的資料型別如下。
struct ApiErrorResponse: Decodable, Error {
let message: String
let status: Int
}
- 上傳的圖片只能是貓咪。The CAT API 會檢查圖片是否是貓咪,若是上傳小狗的圖片會失敗。
- 採用方法 4 & 5 時,利用 multipartDic 判斷是否是要上傳 multipart/form-data 格式。如果不是,而且 http method 是 post 或 put 時,則將 Content-Type 設成 application/json。
if let multipartDic = multipartDic {
request.createMultipartFormData(parameters: multipartDic)
} else if method == .post || method == .put {
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
}