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)")
}
相关推荐
HarderCoder11 小时前
iOS 知识积累第一弹:从 struct 到 APP 生命周期的全景复盘
ios
叽哥1 天前
Flutter Riverpod上手指南
android·flutter·ios
用户092 天前
SwiftUI Charts 函数绘图完全指南
ios·swiftui·swift
YungFan2 天前
iOS26适配指南之UIColor
ios·swift
权咚3 天前
阿权的开发经验小集
git·ios·xcode
用户093 天前
TipKit与CloudKit同步完全指南
ios·swift
法的空间3 天前
Flutter JsonToDart 支持 JsonSchema
android·flutter·ios
2501_915918413 天前
iOS 上架全流程指南 iOS 应用发布步骤、App Store 上架流程、uni-app 打包上传 ipa 与审核实战经验分享
android·ios·小程序·uni-app·cocoa·iphone·webview
00后程序员张3 天前
iOS App 混淆与加固对比 源码混淆与ipa文件混淆的区别、iOS代码保护与应用安全场景最佳实践
android·安全·ios·小程序·uni-app·iphone·webview
Magnetic_h3 天前
【iOS】设计模式复习
笔记·学习·ios·设计模式·objective-c·cocoa