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)")
}
相关推荐
Magnetic_h14 小时前
【iOS】单例模式
笔记·学习·ui·ios·单例模式·objective-c
归辞...16 小时前
「iOS」——单例模式
ios·单例模式·cocoa
yanling202317 小时前
黑神话悟空mac可以玩吗
macos·ios·crossove·crossove24
归辞...19 小时前
「iOS」viewController的生命周期
ios·cocoa·xcode
crasowas1 天前
Flutter问题记录 - 适配Xcode 16和iOS 18
flutter·ios·xcode
2401_852403551 天前
Mac导入iPhone的照片怎么删除?快速方法讲解
macos·ios·iphone
SchneeDuan1 天前
iOS六大设计原则&&设计模式
ios·设计模式·cocoa·设计原则
JohnsonXin2 天前
【兼容性记录】video标签在 IOS 和 安卓中的问题
android·前端·css·ios·h5·兼容性
蒙娜丽宁2 天前
Go语言错误处理详解
ios·golang·go·xcode·go1.19
名字不要太长 像我这样就好2 天前
【iOS】push和pop、present和dismiss
学习·macos·ios·objective-c·cocoa