Article directory
Preface
Learning swift continues the previous idea, learning from OC, starting from the UI, and learning the corresponding adaptive layout.
Today I learned again about swift’s native network requests and the corresponding third-party library-Alamofire.
Import library
- Due to computer configuration reasons, I learned a new method of importing third-party libraries.
Swift Package Manager
. - First, go to the readme file on the official website of the library to find it.
- Copy
Swift Package Manager
the url at the bottom. - Go to the general framework of the project
- Add Other Package in the lower left corner
Enter the URL in the upper right corner to search for the library and add it.
Native network request
- The idea of native network requests and OC are exactly the same. Create a URL, construct a request, send the request, and get the data.
// 普通的网络请求
func makeLogon() {
// 构建URL
let url:URL = URL(string: "https://news-at.zhihu.com/api/4/news/latest")!
// 发送HTTP请求的的session对象
let session = URLSession.shared
// 构建请求request
var request = URLRequest(url: url)
request.httpMethod = "GET"
// 发一个get请求
let task = session.dataTask(with: request as URLRequest) {
(
data, response, error) in
guard let data = data, let _:URLResponse = response, error == nil else {
print("Request Erroor")
return
}
let dataString = String(data: data, encoding: String.Encoding.utf8)
let dict = self.getDictionaryFromJSONString(jsonString: dataString!)
print(dict)
}
task.resume()
}
This code uses URLSession to initiate a GET request and converts the returned data into a dictionary type.
-
First,
session.dataTask(with:completionHandler:)
create a task object through the method and handle the result of the request in the closure. -
In the closure, optional binding is first used to check whether
guard let
the request's return datadata
exists, andresponse
whether the response exists and isURLResponse
of type, and checks for errorserror
. If any of the conditions are not met, an error message will be printed and returned. -
If there are no errors, we convert the returned data to string type
data
usingString(data:encoding:)
the method and store it indataString
the variable. -
Next, call
getDictionaryFromJSONString(jsonString:)
the method to convert the string type datadataString
to the dictionary type. -
Finally, print the converted dictionary
dict
.
getDictionaryFromJSONString(jsonString:)
Is a custom method used to convert JSON string to dictionary type.
- Because the requested data is not of dictionary type, we need to write a dictionary conversion method for it.
func getDictionaryFromJSONString(jsonString: String) -> NSDictionary {
// 将传入的 JSON 字符串 jsonString 使用 data(using:) 方法转换为 Data 类型
let jsonData:Data = jsonString.data(using: .utf8)!
// 通过 JSONSerialization.jsonObject(with:options:) 方法将 jsonData 进行 JSON 解析,并将解析结果存储在 dict 变量中。这里使用的选项是 .mutableContainers,表示可以修改容器对象
let dict = try? JSONSerialization.jsonObject(with: jsonData, options: .mutableContainers)
// 使用条件语句判断 dict 是否为 nil。如果不为 nil,表示 JSON 解析成功,将 dict 强制转换为 NSDictionary 类型,并返回。
// 如果 dict 为 nil,表示 JSON 解析失败,返回一个空的 NSDictionary 对象。
if dict != nil {
return dict as! NSDictionary
}
return NSDictionary()
}
Singleton encapsulates a native network request
Here we still take the get request as an example to request the interface of Zhihu Daily
- Create a singleton class
- initialization
static let shareSingenal = Mananger()
Build function and send request
Swift closures are used here to write success or failure callbacks.
Used if let syntax: very safe
func getWithPath(path: String,paras: Dictionary<String,Any>?,success: @escaping ((_ result: Any) -> ()),failure: @escaping ((_ error: Error) -> ())) {
// var i = 0
let address = path
// 首先,定义了变量 i 和 address,用于拼接完整的 URL 地址。
// if let paras = paras {
// for (key,value) in paras {
// if i == 0 {
// address += "?\(key)=\(value)"
// }else {
// address += "&\(key)=\(value)"
// }
// i += 1
// }
// }
// 完成参数拼接后,通过 URL(string:) 方法将拼接后的 address 转换为 URL 对象。
let url = URL(string: address.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)!)
// 使用 URLSession.shared 创建一个共享的会话对象,并通过 dataTask(with:completionHandler:) 方法发起网络请求。
let session = URLSession.shared
let dataTask = session.dataTask(with: url!) {
(data, respond, error) in
if let data = data {
// 在网络请求的回调闭包中,首先判断返回的数据 data 是否存在。如果存在,则通过 JSONSerialization.jsonObject(with:options:) 方法将数据进行 JSON 解析,并将解析结果传递给成功回调闭包 success。
if let result = try? JSONSerialization.jsonObject(with: data, options: .allowFragments){
success(result)
}
}else {
// 如果数据不存在,即请求失败,将错误信息 error 传递给失败回调闭包 failure。
failure(error!)
}
}
// 通过调用 dataTask.resume() 方法开始执行网络请求。
dataTask.resume()
}
}
Alamofire
Alamofire
isSwift
a network library developed using the language, which isAFNetworking
very similar toAlamofire
Implemented using chain programming. It has the characteristics of concise syntax, good performance and excellent readability.Alamofire
, essentially based onNSURLSession
encapsulation, its core isURLSession
andURLSessionTask
subclasses. Its early versions useAlamofire.request
(), and after 5.0, useAF.request
().
Essentially, the third-party library is to reduce our pressure and reduce the code of the request process.
usage
The most basic thing is to send a GET request
func sendReqWithAlamofire() -> Void {
let url: URL = URL(string: "https://news-at.zhihu.com/api/4/news/latest")!
AF.request(url).response {
response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
}
It can be seen that the success and failure callbacks have been encapsulated for us.
It should be noted here that the above data is printed.
- In
Alamofire
,response
thedata
attribute is an optional typeData?
. Therefore, shown in the printed resultsOptional
means that the value is optional. And 3643 bytes represents the number of bytes of the returned data. This value will change according to the actual size of the returned data. - Here’s how to convert a dictionary
For the AF request
request interface, Alamofire
three interfaces with the same name are encapsulated, and the three interfaces are set for different parameters.
open func request(_ convertible: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoding: ParameterEncoding = URLEncoding.default,
headers: HTTPHeaders? = nil,
interceptor: RequestInterceptor? = nil,
requestModifier: RequestModifier? = nil)
open func request<Parameters: Encodable>(_ convertible: URLConvertible,
method: HTTPMethod = .get,
parameters: Parameters? = nil,
encoder: ParameterEncoder = URLEncodedFormParameterEncoder.default,
headers: HTTPHeaders? = nil,
interceptor: RequestInterceptor? = nil,
requestModifier: RequestModifier? = nil)
open func request(_ convertible: URLRequestConvertible, interceptor: RequestInterceptor? = nil)
Parameter 1: convertible
(Variable) A variable parameter. In fact, it is the requested url address.
Parameter two: method
request method. It is what we often call GET and POST.
Parameter three: parameters
request parameters. The parameter part of the business data, such as the login module userName
, Password
etc. Business data.
Parameter four: encoding
encoding method. Alamofire
Two encoding methods are supported:
JSONParameterEncoder
And -URLEncodedFormParameterEncoder
if the encoding is set to JSONEncoding, it is in JSON format.
Parameter five: headers
Request header parameters. http
Parameter settings for the request header in the request, supporting Json
formats, such as settings token
, cookie
and other parameters. This still requires writing different requirements based on different interfaces.
Parameter six: interceptor
Request interceptor, mainly used to intercept requests during the request process and perform some necessary processing on the request. (Not used)
Parameter seven: requestModifier
Request modifier. Modify data during the request process, for example, for a specific request, do not use the default timeout but customize the timeout.
Alamofire return response
Alamofire supports 4 return response processing methods: Data, String, JSON, and custom types.
let url: URL = URL(string: "https://news-at.zhihu.com/api/4/news/latest")!
//Data示例
AF.request(url).responseData {
response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
//String示例
AF.request(url).responseString {
response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
//JSON示例
AF.request(url).responseJSON {
response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
//自定义格式示例
struct PersonResponse: Decodable {
let name: String, let nickName : String, let age : Int }
AF.request(url).responseDecodable(of: PersonResponse.self) {
response in
switch response.result {
case let .success(data):
print("data:\(String(describing: data))")
case let .failure(error):
print(error)
}
}
Convert the returned data into a dictionary/string
The security of the language is very strong. I still use the if let structure first, which is also used in the success callback.
func sendReqWithAlamofire() -> Void {
let url: URL = URL(string: "https://news-at.zhihu.com/api/4/news/latest")!
AF.request(url).response {
response in
switch response.result {
// 涉及到了语言的安全性
case let .success(data):
print("Successd get ReqWithAla")
print(data as Any)
// 转字符串
if let responseData = data {
let dataString = String(data: responseData, encoding: .utf8)
print("data: \(String(describing: dataString))")
}
// print("data:\(String(describing: data))")
// 转字典
if let responseData = data {
do {
// 首先使用可选绑定 if let 检查 data 是否存在。如果 data 存在,我们尝试使用 JSONSerialization.jsonObject(with:options:) 方法将数据解析为字典类型。
if let jsonToDict = try JSONSerialization.jsonObject(with: responseData, options: []) as? [String: Any] {
// 使用转换后的字典进行进一步操作
print("data: \(jsonToDict)")
}
} catch {
// 解析失败,会抛出异常,我们可以使用 catch 块来捕获异常并进行相应的错误处理。
print("Failed to parse JSON: \(error)")
}
}
case let .failure(error):
print(error)
}
}
}
}
Summarize
Like the AFN library, it is easy and fast to use. Swift’s language feature security is reflected in many places. Next, we will learn about Swift’s original json Model parsing library.