0%

API連線處理

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
///API名稱列舉,方便呼叫,可擴充
enum APIDataModel:APIProtocol {
case randomUser(gender:String?=nil)
case getIpDetail(ip:String)
}

extension APIDataModel {
///API的網域
var domain: String {
switch self {
case .randomUser:
return "https://randomuser.me"
case .getIpDetail:
return "https://api.iplegit.com"
}
}

///API的完整網址
var url: URL {
guard let url = URL(string: domain+path) else {
fatalError("baseURL could not be configured.")
}
return url
}

///API的路徑
var path: String {
switch self {
case .randomUser:
return "/api/"
case .getIpDetail:
return "/full"
}
}

/**
可根據需求切換或新增方式
GET、HEAD、POST、PUT、DELETE...
*/
var httpMethod: HTTPMethod {
switch self {
case .randomUser:
return .get
case .getIpDetail:
return .get
}
}

/**
根據API使用對應的傳送方式,例如formData等...
*/
var task: HTTPTask {
switch self {
case .randomUser(let gender):
return .requestUrlParameters(parameters: ["gender":gender ?? ""])
case .getIpDetail(let ip):
return .requestUrlParameters(parameters: ["ip":ip])
}
}

///若有每支API都需傳送的值可寫在這裡,例如APIKey
var commonParameter: [String : Any]? {
return nil
}
}

處理回傳與解析

根據後端給的資料,需要自行建立model,請參考Codable JSON用法。

  1. 在範例裡,建立一個名為APIManager的物件並遵循APILoader協議:
1
2
3
class APIManager: APILoader {

}
  1. 創立兩個函式

請求部分:

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
/**
處理與解析API內容
- Parameter api: API
- Parameter responseData: 傳回來的資料
- Returns: (資料, 錯誤資訊)
*/
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

}
tags: ‘程式碼’ ‘API’