开发iOS App 时,我们时常需要跟网路上的后台(server) 沟通。如下图所示,我们的App 是client,它会发送request 给server,然后server 再回传response,比方将JSON 格式的电影资料回传给App。
HTTP method (request type)
当App 发送request 给网络服务器接口时,目前最常见的方法是透过http 或https,而http(https) 传送的request 有个重要的method 属性,可以说明request 的目的为何。
比较常用的http(https) method 有以下几种:
- GET: 取得资料。
- POST: 建立资料。
- DELETE: 删除资料。
- PUT / PATCH: 修改更新资料。
具体介绍可以查看这里:https://developer.mozilla.org/zh-CN/docs/Web/HTTP/Methods
使用HTTP method 表示request 目的
串接API 有很多写法,因为后台工程师可以自订资料的格式和处理方式,比方他可以规定读取,新增和删除资料的request 都是post,透过上传的JSON 资料区分读取,新增和删除。
不过目前比较常见的主流是采用REST API((RESTful API),它可以让我们串接的API 有个统一的标准,使用HTTP method 的GET,POST,DELETE & PUT 区分读取,新增,删除和修改。
想进一步了解REST API 的朋友,可查看这个链接:https://www.techtarget.com/searchapparchitecture/definition/RESTful-API
使用Reqres API 展示
Reqres API网址:https://reqres.in
为了示范如何使用URLSession 串接http get,post,delete,put API,接下来我们将以方便测试API 的reqres 为例说明。
Reqres API 提供丰富的API,帮助我们方便测试GET,POST,DELETE,PUT & PATCH。
使用 GET 方式请求数据
呼叫dataTask(with:completionHandler:),传入URL 即可产生搭配http method GET 的request 抓取资料。
let url = URL(string: " https://reqres.in/api/users?page=1 ")!
URLSession.shared.dataTask(with: url) { data, response, error in
if let data = data,
let content = String(data: data, encoding: .utf8) {
print(content)
}
}.resume()
也可以呼叫dataTask(with:completionHandler:),传入URLRequest,它也会搭配http method GET。
let url = URL(string: " https://reqres.in/api/users?page=1 ")!
var request = URLRequest(url: url)
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data,
let content = String(data: data, encoding: .utf8) {
print(content)
}
}.resume()
使用 POST 方式新增数据
api说明:
struct CreateUserBody: Encodable {
let name: String
let job: String
}
struct CreateUserResponse: Decodable {
let name: String
let job: String
let id: String
}
let url = URL(string: " https://reqres.in/api/users ")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
let user = CreateUserBody(name: "Peter", job: "情歌王子")
let data = try? encoder.encode(user)
request.httpBody = data
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
do {
let decoder = JSONDecoder()
let createUserResponse = try decoder.decode(CreateUserResponse.self, from: data)
print(createUserResponse)
} catch {
print(error)
}
}
}.resume()
说明
request.httpMethod = "POST"
将httpMethod 设为POST,可以写大写的POST,也可以写小写的post。
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
将http header 的Content-Type 设为application/json,因为reqres API 上传的资料格式为JSON。上传的格式不一定会是json,比方application/x-www-form-urlencoded & multipart/form-data 也是常见的格式。
request.httpBody = data
从URLRequest 的httpBody 设定上传的资料。
ps: 除了使用dataTask(with:completionHandler:) 上传资料,我们也可以用uploadTask(with:from:completionHandler:),将资料带在参数from 里。
let url = URL(string: " https://reqres.in/api/users ")!
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
let user = CreateUserBody(name: "Peter", job: "情歌王子")
let data = try? encoder.encode(user)
URLSession.shared. uploadTask (with: request, from: data ) { data, response, error in
if let data = data {
do {
let decoder = JSONDecoder()
let createUserResponse = try decoder.decode(CreateUserResponse.self, from:data)
print(createUserResponse)
} catch {
print(error)
}
}
}.resume()
使用 DELETE 方式删除数据
api说明:
let url = URL(string: " https://reqres.in/api/users/2 ")!
var request = URLRequest(url: url)
request.httpMethod = "DELETE"
URLSession.shared.dataTask(with: request) { data, response, error in
if let httpResponse = response as? HTTPURLResponse {
print(httpResponse.statusCode)
}
}.resume()
使用 PUT / PATCH 方式修改数据
api说明:
import UIKit
struct UpdateUserBody: Encodable {
let name: String
let job: String
}
struct UpdateUserResponse: Decodable {
let name: String
let job: String
}
let url = URL(string: " https://reqres.in/api/users/2 ")!
var request = URLRequest(url: url)
request.httpMethod = "PUT"
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let encoder = JSONEncoder()
let user = UpdateUserBody(name: "Peter", job: "情歌王子")
let data = try? encoder.encode(user)
request.httpBody = data
URLSession.shared.dataTask(with: request) { data, response, error in
if let data = data {
do {
let decoder = JSONDecoder()
let updateUserResponse = try decoder.decode(UpdateUserResponse.self, from:data)
print(updateUserResponse)
} catch {
print(error)
}
}
}.resume()