iOS 之网络请求

引言

iOS 开发中进行网络请求有两种主要方式:使用苹果原生的URLSession和使用第三方库Alamofire,下面将对这两种网络请求方式进行分别介绍

URLSession

概述

URLSession是苹果官方提供的原生的网络请求框架,提供了与网络通信相关的一系列类和方法。然而,使用纯粹的 URLSession进行网络请求可能需要处理很多底层细节,如构建请求处理响应处理错误

示例

swift 复制代码
import Foundation

class Service {
    func requestWithURLSession() {
        guard let url = URL(string: "") else {
            return
        }

        URLSession.shared.dataTask(with: url) { data, response, error in
            if let error = error { 
                print("Error: \(error)") 
            } else if let data = data { 
                DispatchQueue.main.async { 
                    self.data = data 
                } 
            }
        }.resume()
    }
}

Alamofire + CocoaPods

Alamofire

Alamofire是一个在URLSession基础上进行封装的第三方网络请求库,封装了URLSession的诸多底层细节,提供了更友好的API。它旨在简化网络请求的编写和管理,提供了更高级的抽象,使得网络请求变得更加易用和灵活,让开发者能够更专注于业务逻辑而不是网络细节

通过使用Alamofire,可以更轻松地执行常见的网络请求操作,处理认证上传下载错误处理等。它还支持链式调用和响应验证等功能,让你的代码更具可读性和可维护性

请求方法与响应方法

Alamofire提供了一系列方法来处理不同类型的请求和响应,以满足不同场景的需求。下面将介绍一些常见的Alamofire请求和响应的处理方法

请求处理方法

Alamofire提供了多种方法来创建和发起网络请求。以下是一些常用的 Alamofire 请求方法:

  1. AF.request() :发起一个常规的HTTP 请求,支持不同的HTTP 方法GETPOSTPUTDELETE等)和参数,可以在响应闭包中处理返回的数据和错误

  2. AF.upload() :用于上传文件或数据,可以在响应闭包中处理上传进度、响应数据和错误

  3. AF.download() :用于下载文件,可以在响应闭包中处理下载进度、下载后的文件路径和错误

  4. AF.streamRequest() :用于处理流式的网络请求,适用于长连接或服务器推送等场景

响应处理方法
  1. response : 处理通用的响应数据,可以在闭包中访问响应的状态码、头部和数据。适用于通用的JSON、文本等响应
swift 复制代码
AF.request("").response { response in
    if let data = response.data {
        print("Response Data: \(data)")
    }
    if let statusCode = response.response?.statusCode {
        print("Status Code: \(statusCode)")
    }
}
  1. responseJSON : 将响应的数据解析为JSON 格式,并在闭包中处理解析后的 JSON 数据
swift 复制代码
AF.request("").responseJSON { response in
    switch response.result {
    case .success(let json):
        print("JSON Response: \(json)")
    case .failure(let error):
        print("Error: \(error)")
    }
}
  1. responseDecodable : 使用Codable 协议将响应的数据解码为特定的数据模型,适用于处理JSON 数据的自动解析
swift 复制代码
struct Post: Codable {
    let userId: Int
    let id: Int
    let title: String
    let body: String
}

AF.request("").responseDecodable(of: Post.self) { response in
    switch response.result {
    case .success(let post):
        print("Post Title: \(post.title)")
    case .failure(let error):
        print("Error: \(error)")
    }
}

AF.responseDecodable方法可以替代手动创建JSONDecoder实例并使用decode方法来解析数据

swift 复制代码
AF.request("").response { response in
    if let data = response.data {
        let decoder = JSONDecoder()
        let post = try decoder.decode(Post.self, from: data)
        print("Post Title: \(post.title)")
    }
    if let statusCode = response.response?.statusCode {
        print("Status Code: \(statusCode)")
    }
}
  1. responseData : 以原始数据的形式返回响应数据,适用于处理二进制数据
swift 复制代码
AF.request("").responseData { response in
    switch response.result {
    case .success(let imageData):
        print("Image Data: \(imageData)")
    case .failure(let error):
        print("Error: \(error)")
    }
}
  1. downloadProgress : 在下载请求中,可以使用此方法来监听下载进度的变化
swift 复制代码
AF.download("").downloadProgress { progress in
    print("Download Progress: \(progress.fractionCompleted)")
}
.response { response in
    print("Download Completed!")
}
  1. uploadProgress : 在上传请求中,可以使用此方法来监听上传进度的变化
swift 复制代码
let image = UIImage(named: "example.jpg")!

AF.upload(image, to: "").uploadProgress { progress in
    print("Upload Progress: \(progress.fractionCompleted)")
}
.response { response in
    print("Upload Completed!")
}

示例

swift 复制代码
import Foundation
import Alamofire

class Service {
    func requestWithAlamofire() {
        guard let url = URL(string: "") else {
            return
        }

        AF.request(url).responseData { response in
            switch response.result {
            case .success(let data): 
                DispatchQueue.main.async { 
                    self.data = data 
                } 
            case .failure(let error): 
                print("Error: \(error)") }
            }
        }
    }
}

CocoaPods

CocoaPods是一个用于管理SwiftObjective-C项目中第三方库包管理器。它可以轻松地集成和管理各种库,从而减少了手动管理库的复杂性。想了解更多就去 CocoaPods官网 看看

下面是CocoaPodsmacOS上的安装步骤:

  1. 安装CocoaPods

    在终端中运行以下命令来安装CocoaPods及其所依赖的Ruby环境(若没有):

    bash 复制代码
    sudo gem install cocoapods

    macOS自带了Ruby,可以在执行上面命令时在终端中运行以下命令来检查:

    bash 复制代码
    ruby -v

    CocoaPods是基于Ruby编写的

  2. 验证安装

    安装完成后,可以运行以下命令来验证是否安装成功:

    bash 复制代码
    pod --version

    如果安装成功,将显示CocoaPods的版本号

  3. 定期更新

    CocoaPods的版本和依赖可能会发生变化,所以建议定期更新CocoaPods以保持最新。可以使用以下命令来更新CocoaPods

    bash 复制代码
    sudo gem update cocoapods

拓展

  1. Alamofire各类请求的响应类型都是DataResponse类型,包含了诸多属性:requestresponsedataresultvalue

    • request:表示原始的请求对象,包含了请求的URLHTTP 方法等信息
    • response:表示响应对象,包含了服务器返回的HTTP 响应,其中可能包含状态码头部信息
    • data:表示原始的响应数据,以字节数组Data的形式存储,适用于需要手动处理原始数据的情况
    • result:一个Result枚举的关联值,表示请求的结果。Result枚举可以包含成功的情况(带有数据关联值)或失败的情况(带有错误关联值)
    • value:表示result的枚举值,如果请求成功,会包含成功数据的枚举值;如果请求失败,则包含失败信息的枚举值
  2. Alamofire中,responseresponseJSONresponseDataresponseDecodable等方法都是为了方便开发者处理不同类型的响应数据而设计的。response返回的是原始数据,而其他方法则提供了更高层次的抽象来方便处理不同类型的数据。其中,responseJSONresponseDataresponseDecodable等方法都是对response方法进一步的封装,用来更方便处理不同类型的响应数据,比如将JSON 数据解析成字典数组,或者解析成遵循 Decodable 协议的模型对象

  3. responseresponseJSONresponseDataresponseDecodable响应的result属性类型

    • response
      • result属性的类型是Result<Data, AFError>
      • response方法并未对响应数据做类型处理,所以是原始响应数据类型
    • responseJSON
      • result属性的类型是Result<Any, AFError>
      • responseJSON方法将响应数据解析为JSON 格式JSON可以包含任何类型的数据,因此解析后的类型是Any
    • responseData
      • result属性的类型是Result<Data, AFError>
      • responseData方法直接返回原始的二进制数据,解析后的类型是Data
    • responseDecodable
      • result属性的类型是Result<DecodableType, AFError>
      • responseDecodable方法将响应数据解析为特定的遵循Decodable协议的数据类型,解析后的类型是指定的模型对象类型

    这种设计使得在处理不同类型的网络请求结果时,可以根据需要进行适当的类型转换和操作。通过使用不同的方法,Alamofire将响应结果解析成适合特定情况的类型,使得处理网络请求变得更加灵活和方便

  4. responseData方法的响应对象的dataresultvalue属性值的类型都是Data,且值也都是一样的

  5. 枚举关联值是指在声明枚举成员时,可以附加额外的数据信息,以便在实际使用中可以存储和处理更多的信息。关联值使得枚举成员更加灵活,能够表示不同的数据情况,而不仅仅是通过简单的标签表示

swift 复制代码
// suspended 和 banned 这两个枚举成员都附带了关联值
enum UserStatus {
    case active
    case suspended(reason: String)
    case banned(reason: String, duration: Int)
}
swift 复制代码
// 关联值只有类型,没有声明变量
@frozen public enum Result<Success, Failure> where Failure : Error { 
    case success(Success) 
    case failure(Failure) 
}

// 使用时指定变量
let result: Result<Int, Error> = .success(42)

switch result {
case .success(let value):
    print("Success: \(value)")
case .failure(let error):
    print("Failure: \(error)")
}
相关推荐
程序猿看视界3 小时前
如何在 UniApp 中实现 iOS 版本更新检测
ios·uniapp·版本更新
dr李四维6 小时前
iOS构建版本以及Hbuilder打iOS的ipa包全流程
前端·笔记·ios·产品运营·产品经理·xcode
️ 邪神6 小时前
【Android、IOS、Flutter、鸿蒙、ReactNative 】自定义View
flutter·ios·鸿蒙·reactnative·anroid
比格丽巴格丽抱18 小时前
flutter项目苹果编译运行打包上线
flutter·ios
网络安全-老纪19 小时前
iOS应用网络安全之HTTPS
web安全·ios·https
1024小神1 天前
tauri2.0版本开发苹果ios和安卓android应用,环境搭建和最后编译为apk
android·ios·tauri
lzhdim1 天前
iPhone 17 Air看点汇总:薄至6mm 刷新苹果轻薄纪录
ios·iphone
安和昂1 天前
【iOS】知乎日报第四周总结
ios
麦田里的守望者江1 天前
KMP 中的 expect 和 actual 声明
android·ios·kotlin
_黎明1 天前
【Swift】字符串和字符
开发语言·ios·swift