[iOS_Swift_Alamofire implements network requests]

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.Please add image description
  • Copy Swift Package Managerthe url at the bottom.
  • Go to the general framework of the project
    Please add image description
  • Please add image description
  • Add Other Package in the lower left corner
  • Please add image description
  • Please add image description
    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.

  1. First, session.dataTask(with:completionHandler:)create a task object through the method and handle the result of the request in the closure.

  2. In the closure, optional binding is first used to check whether guard letthe request's return data dataexists, and responsewhether the response exists and is URLResponseof type, and checks for errors error. If any of the conditions are not met, an error message will be printed and returned.

  3. If there are no errors, we convert the returned data to string type datausing String(data:encoding:)the method and store it in dataStringthe variable.

  4. Next, call getDictionaryFromJSONString(jsonString:)the method to convert the string type data dataStringto the dictionary type.

  5. 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()
    }
    

Please add image description

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
    Please add image description
  • 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

  • Alamofireis Swifta network library developed using the language, which is AFNetworkingvery similar to
  • AlamofireImplemented using chain programming. It has the characteristics of concise syntax, good performance and excellent readability.
  • Alamofire, essentially based on NSURLSessionencapsulation, its core is URLSessionand URLSessionTasksubclasses. Its early versions use Alamofire.request(), and after 5.0, use AF.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.Please add image description

  • In Alamofire, responsethe dataattribute is an optional type Data?. Therefore, shown in the printed results Optionalmeans 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 requestrequest interface, Alamofirethree 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: methodrequest method. It is what we often call GET and POST.
Parameter three: parametersrequest parameters. The parameter part of the business data, such as the login module userName, Passwordetc. Business data.
Parameter four: encodingencoding method. AlamofireTwo encoding methods are supported:

  • JSONParameterEncoderAnd - URLEncodedFormParameterEncoderif the encoding is set to JSONEncoding, it is in JSON format.

Parameter five: headersRequest header parameters. httpParameter settings for the request header in the request, supporting Jsonformats, such as settings token, cookieand other parameters. This still requires writing different requirements based on different interfaces.
Parameter six: interceptorRequest interceptor, mainly used to intercept requests during the request process and perform some necessary processing on the request. (Not used)
Parameter seven: requestModifierRequest 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.

Guess you like

Origin blog.csdn.net/weixin_61639290/article/details/131116785