API連線處理 NetworkRouter [TOC]
用途 可以因應各種網域及路徑,實現快速切換並呼叫API
資源庫位置:github NetworkRouter
使用方式 訂定列舉 使用列舉(Enum)創建並遵循APIProtocol協議,case後方為相關值(Associated Value)可以用API名稱命名,方便日後呼叫。
APIProtocol已有訂定幾個基本的屬性:
domain: api的網域,有時候呼叫的api不一定會在同一個網域(例如額外使用firebase函式庫)
url: 完整的網址
path: 網域後面的路徑
httpMethod: 根據對應的api使用對應的httpMethod(這裡只有使用get或post,可依照需求自行擴充)
task: 根據API使用對應的傳送方式,例如formData等…
commonParameter: 每支API都需傳送的參數,例如APIKey
若有特殊需求可自行擴充,例如需要額外增加header。
範例: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 23 24 25 26 27 28 29 30 31 32 33 34 35 36 37 38 39 40 41 42 43 44 45 46 47 48 49 50 51 52 53 54 55 56 57 58 59 60 61 62 63 64 65 enum APIDataModel :APIProtocol { case randomUser(gender:String ?= nil ) case getIpDetail(ip:String ) } extension APIDataModel { var domain: String { switch self { case .randomUser: return "https://randomuser.me" case .getIpDetail: return "https://api.iplegit.com" } } var url: URL { guard let url = URL (string: domain+ path) else { fatalError ("baseURL could not be configured." ) } return url } var path: String { switch self { case .randomUser: return "/api/" case .getIpDetail: return "/full" } } var httpMethod: HTTPMethod { switch self { case .randomUser: return .get case .getIpDetail: return .get } } var task: HTTPTask { switch self { case .randomUser(let gender): return .requestUrlParameters(parameters: ["gender" :gender ?? "" ]) case .getIpDetail(let ip): return .requestUrlParameters(parameters: ["ip" :ip]) } } var commonParameter: [String : Any ]? { return nil } }
處理回傳與解析 根據後端給的資料,需要自行建立model,請參考Codable JSON 用法。
在範例裡,建立一個名為APIManager的物件並遵循APILoader協議:
1 2 3 class APIManager : APILoader {}
創立兩個函式
請求部分: 1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 class func sendAPI (api :APIDataModel , completion :(APICompletion )?=nil ) { sendRequest(api: api) { (responseData, response, error) in if let completion = completion { if let error = error { completion(nil , error) return } if let data = responseData { let result = checkResult(api: api, responseData: data) completion(result,"nil" ) } else { completion(nil ,"Data is empty" ) } } } }
解析部分: 這裡的RandomUser與IpDetail是利用Codable JSON自行建立的資料型態。
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 private class func checkResult (api :APIDataModel , responseData :Data ) -> Any ? { do { switch api { case .getIpDetail: let result = try JSONDecoder ().decode(IpDetail .self , from: responseData) return result case .randomUser: let result = try JSONDecoder ().decode(RandomUser .self , from: responseData) return result } } catch { return NetworkResponse .unableToDecode.rawValue } }
呼叫方式 1 2 3 APIManager .sendAPI(api: .randomUser(gender: "male" )) { (result, error) in }