前言:
我们在开发专案时常常需要跟网路上的後台(Server)沟通互动,这就必须用到网路请求,我们会发送 request
给 Server,Server 会再回传 response
来串接网路上Server 的API,而 iOS 在 iOS 9 之後使用NSURLSession
实现网路请求,透过NSURLSession
的URLSession
物件建立一个请求Task,然後执行Task 即可,包括快取、多执行绪任务等 iOS 都已经在sdk 层面封装完毕
以下我们就来看看如何使用URLSession
串接 RESTful API,我们用Reqres API 来示范,串接API 会使用到的Data Model 可以参考Codable JSON 教学
首先我们根据以上的Request Body 以及Response 建立关於Post Sample 的Model
User.swift
:
struct UserRequestBody: Encodable {
var name: String
var job: String
}
struct UserPostResponse: Decodable {
var name: String
var job: String
var id: String?
var dateCreated: Date?
var modifiedId: String {
if let newId = id {
return newId
} else {
return "******"
}
}
var modifiedDateCreated: String {
let dateFormatter = DateFormatter()
dateFormatter.dateStyle = .medium
if let newDate = dateCreated {
return dateFormatter.string(from: newDate)
} else {
return "******"
}
}
enum CodingKeys: String, CodingKey {
case name
case job
case id
case dateCreated = "createdAt"
}
}
接着建立UserURLSession.swift
来处理关於URLSession
的事件
import Foundation
class UserURLSession {
static let shared = UserURLSession()
func userPostRequest(userRequestBody:UserRequestBody,completionHandler: @escaping (UserPostResponse) -> Void) {
let url = URL(string: "https://reqres.in/api/users")!
// MARK: URLRequest
var request = URLRequest(url: url)
request.httpMethod = "POST"
request.addValue("application/json", forHTTPHeaderField: "Content-Type")
guard let httpBody = try? JSONEncoder().encode(userRequestBody) else {
print("Invalid httpBody")
return
}
// MARK: Set httpBody
request.httpBody = httpBody
URLSession.shared.dataTask(with: request) {
data, response, error in
if let data = data {
do {
let decoder = JSONDecoder()
decoder.dateDecodingStrategy = .formatted(DateFormatter.customFormatter)
let user = try decoder.decode(UserPostResponse.self, from: data)
completionHandler(user)
}catch(let error) {
print(error.localizedDescription)
}
} else {
print("No Data")
}
}.resume()
}
}
extension DateFormatter {
static let customFormatter: DateFormatter = {
let formatter = DateFormatter()
formatter.dateFormat = "yyyy-MM-dd'T'HH:mm:ss.SSS'Z'"
formatter.calendar = Calendar(identifier: .iso8601)
formatter.timeZone = TimeZone(secondsFromGMT: 0)
formatter.locale = Locale(identifier: "en_us_POSIX")
return formatter
}()
}
之後在View 设计画面并使用
POSTSampleView.swift
:
struct POSTSampleView: View {
@State private var name = "Ryder"
@State private var job = "Engineer"
@State var user :UserPostResponse = UserPostResponse(name: "*****", job: "*****", id: nil, dateCreated: nil)
var body: some View {
NavigationView {
VStack {
List(){
Text("POST sample")
Section(header: Text("Request Data")) {
TextField("Name: ", text: $name)
TextField("Job: ", text: $job)
}
}
List() {
Section(header: Text("Response Data")) {
Text("Name: \(user.name)")
Text("Job: \(user.job)")
Text("ID: \(user.modifiedId)")
Text("Date created: \(user.modifiedDateCreated)")
}
}
.listStyle(GroupedListStyle())
Button {
UserURLSession.shared.userPostRequest(userRequestBody: UserRequestBody(name: name, job: job)) { newUser in
DispatchQueue.main.async {
user = newUser
}
}
} label: {
Text("POST Request")
}
.padding()
.foregroundColor(Color.white)
.background(Color.green)
.cornerRadius(8)
}
.navigationBarTitleDisplayMode(.inline)
.navigationTitle(Text("URLSession POST Sample"))
}
}
}
struct POSTSampleView_Previews: PreviewProvider {
static var previews: some View {
POSTSampleView()
}
}
这边所有URLSession 的范例一起放在Github: URLSessionSample 供大家参考
<<: Day21 Plugin 从零开始到上架 - 取得权杖(Android)
隆重介绍 Boxenn! 它是我们专门用来在 legacy code 中导入 DDD 的套件,之後会...
大家好,我是阿飞,今天的题目是演算法初阶题目 Two Sum,让我们一起来看看: 题目来源 Code...
介绍Jenkins的章节即将进入尾声了。事实上你可能会想Jenkins默认介面这麽老气,怎麽就成为全...
因为开启 Vue CLI 时有套用 ESLint,而他似乎希望我缩排为 2 space 所以将 VS...
承上一篇,公开申购公告的纲页页面如下 依照我们会需要的栏位,我们的 model 如下 // // S...