Вызов API в Swift | Кодементор
В настоящее время 99% приложений должны подключаться к серверу через API. Так что дело с нетворкингом весьма важно. Как нам с легкостью управлять вызовом API?
Я уверен, ваши ответы Alamofire
. Ты прав. Alamofire
настолько хорош, что это обязательная библиотека в Swift.Alamofire
, URLSession
или любые другие библиотеки являются коннекторами к серверу. Но как их эффективно использовать — это отдельная история. Я говорю вам сегодня.
Это статическая структура, которую вы используете каждый день для взаимодействия с сервером. Взгляните на его содержание.
static private func getHeaders() -> [String: String]? {
return [
"Content-Type": "application/json",
"access_token": "your access token or api key"
]
}
Большинству запросов нужны заголовки, где вам нужно передать access_token
или же api_key
для авторизации ваших запросов. getHeaders
сделает это. Добавьте сюда свои факторы авторизации, и они будут привязаны к вашим запросам, больше не нужно заботиться.
Что произойдет, если вы захотите настроить заголовок? Потом.
2. URL API
static private func getUrl(from api: String) -> URL? {
let BASE_URL = ""
let apiUrl = api.contains("http") ? api : BASE_URL + api
return URL(string: apiUrl)
}
Вы не хотите повторять везде вы называете API, верно?
Положить ваши BASE_URL
внутри getUrl
только добавить /users/:id
или же /transactions
. Не повторяйтесь.
Нет
"/"
в концеBASE_URL
и всегда запускайте API с"/"
Если вы хотите подключить другой BASE_URL, вы можете передать полный URL-адрес API, например https://custom_website.com/api/v2/users
. Помните, что URL-адрес API должен начинаться с http
или же https
.
3. Запрос
Самая важная часть здесь.
static func request(_ api: String,
method: HTTPMethod,
params: [String: Any]? = nil,
headers: [String: String]? = nil,
successJsonAction: ((_ result: AnyObject) -> Void)? = nil,
successDataAction: ((Data) -> Void)? = nil,
failAction: ((_ error: knError) -> Void)? = nil) {
let finalHeaders = headers ?? getHeaders()
let apiUrl = getUrl(from: api)
connector.newRequest(withApi: apiUrl,
method: method,
params: params,
headers: finalHeaders,
successJsonAction: successJsonAction,
successDataAction: successDataAction,
failAction: failAction)
}
Смотрим параметры.
api
: Передайте здесь свой API, принимается только API или полный URL-адрес API. Я говорил вам во 2 части.method
:HTTPMethod
: .get, .post, .put, .delete…params
: по умолчанию ноль. Вы можете игнорировать его, если параметры не нужно отправлять. В демо я его игнорирую.headers
: здесь вы можете добавить собственные заголовки. Если он равен нулю, будут присоединены заголовки по умолчанию.successJsonAction
,successDataAction
: я поддерживаю 2 способа обработки ответа: вручную анализировать JSON Object и JSONDecoder.
Мне нравится анализировать JSON вручную, я могу обрабатывать сложные объекты, объекты с несколькими вложенными уровнями, добавлять пользовательские свойства, которые я хочу.
Но не могу этого отрицать,JSONDecoder
действительно мощный. Простые объекты или результаты, которые вам нужны, все свойства,JSONDecoder
будет лучшим выбором.failAction
: очевидно, вам нужно обработать ваш запрос в случае сбоя.
4. Разъем
static private var connector = AlamofireConnector()
Да, ты прав. Я поставил коннектор в качестве промежуточного программного обеспечения к библиотеке. Я полагаю, однажды Мэтт уберет Alamofire
, и мы просто добавляем сюда другой коннектор. Это не повлияет на другой код.
Теперь мы используем Alamofire или любые библиотеки для подключения к нашему серверу.
В любом коннекторе есть 2 функции.
1. Беги
func run(withApi api: URL?,
method: HTTPMethod,
params: [String: Any]? = nil,
headers: [String: String]? = nil,
successJsonAction: ((_ result: AnyObject) -> Void)? = nil,
successDataAction: ((Data) -> Void)? = nil,
failAction: ((_ error: knError) -> Void)?) {
guard let api = api else {
failAction?(InvalidAPIError(api: "nil"))
return
}
let encoding: ParameterEncoding = method == .get ?
URLEncoding.queryString :
JSONEncoding.default
Alamofire.request(api, method: method,
parameters: params,
encoding: encoding,
headers: headers)
.responseJSON { (returnData) in
self.answer(response: returnData,
successJsonAction: successJsonAction,
successDataAction: successDataAction,
failAction: failAction)
}
}
Вам необходимо обновить кодировку здесь, если ваш сервер принимает другую кодировку. За 6 лет работы с iOS мне только один раз пришлось его менять.
2. Ответ
private func answer(response: DataResponse<Any>,
successJsonAction: ((_ result: AnyObject) -> Void)? = nil,
successDataAction: ((Data) -> Void)? = nil,
failAction fail: ((_ error: knError) -> Void)?) {
if let statusCode = response.response?.statusCode {
if statusCode == 500 {
return
}
// handle status code here: 401 -> show logout; 500 -> show error
}
if let error = response.result.error {
let err = knError(code: "unknown", message: error.localizedDescription)
fail?(err)
return
}
guard let json = response.result.value as AnyObject?, let data = response.data else {
// handle unknown error
return
}
// handle special error convention from server
// ...
if let successDataAction = successDataAction {
successDataAction(data)
return
}
successJsonAction?(json)
}
Вам нужно обрабатывать ответы здесь. По проектам по разному. Если вы хотите отлаживать ответы, вам нужно поставить здесь точки останова.
Объект Error
в ответ отсутствие информации. Поэтому я обычно создаю новый тип ошибки.
class knError {
var code: String = "unknown"
var message: String?
var rawData: AnyObject?
var displayMessage: String {
return message ?? code
}
init() {}
init(code: String, message: String? = nil, rawData: AnyObject? = nil) {
self.code = code
self.message = message
self.rawData = rawData
}
}
class InvalidAPIError: knError {
private override init() {
super.init()
}
private override convenience init(code: String, message: String? = nil, rawData: AnyObject? = nil) {
self.init()
}
convenience init(api: String) {
self.init()
code = "404"
message = "Invalid API Endpoint"
rawData = api as AnyObject
}
}
Можете добавить UnauthorizationError
или же ForbiddenError
отвечать вашим контроллерам. Это легче понять, чем Error
Правильно?
Вот как я управляю нетворкингом в своих 10 проектах. Чувствуйте себя хорошо с этим и надеюсь, что это полезно для вас, ребята.
Пожалуйста, получите доступ к демо на моем https://github.com/nguyentruongky/CallingAPISwift.
Пожалуйста, не стесняйтесь делиться своими способами или комментариями здесь. Ждем ваших мнений.
Наслаждайтесь кодированием.