Alamofire-初探

Alamofire.png

对于iOS开发者来说,AFNetworking是我们大家所熟知的,而Alamofire呢?Alamofire框架其实就是AFNetworking兄弟,出自于同一个作者。既是同一个作者,那么他们的使用方法,框架结构上应该也是保持一致的。AFNetworkingAlamofire

一、网络请求步骤

  1. 设置请求url
  2. 设置URLRequest对象,配置请求相关信息
  3. 创建会话配置URLSessionConfiguration
  4. 创建会话URLSession
  5. 创建任务和设置请求回调,并发起请求

一般通过以上几个步来完成网络请求,当然要根据不同应用场景来配置请求属性。

二、体验

发起一个请求:

func responseData() {
    let url = "http://onapp.yahibo.top/public/?s=api/test/list"
    Alamofire.request(url).responseJSON {
        (response) in
        switch response.result{
        case .success(let json):
            print("json:\(json)")
            let dict = json as! Dictionary<String, Any>
            let list = dict["data"] as! Array<AnyObject>
            guard let result = [UserModel1].deserialize(from: list) else{return}
            self.observable.onNext(result as [Any])
            break
        case .failure(let error):
            print("error:\(error)")
            break
        }
    }
}
  • responseJSON为相应类型,指定为json数据类型
  • responseAlamofire对服务器响应结果的封装
  • 使用常规解包获取数据headimg
  • 通过HandyJSON转换为模型数据,供UI展示

直接通过Alamofire发起请求通过一个闭包返回请求结果,不需要二次封装使用简单。这里我们没有标明请求类型,没有请求参数,那Alamofire是如何封装这些请求参数的呢,点击进入查看方法定义:

public func request(
    _ url: URLConvertible,
    method: HTTPMethod = .get,
    parameters: Parameters? = nil,
    encoding: ParameterEncoding = URLEncoding.default,
    headers: HTTPHeaders? = nil)
    -> DataRequest
{
    return SessionManager.default.request(
        url,
        method: method,
        parameters: parameters,
        encoding: encoding,
        headers: headers
    )
}

这里已经提供了请求所需要的参数,并设置了默认值,因此外界在没有指定方法时默认为get方式。根据实际开发需求设置响应的参数:

Alamofire.request(url,method: .post,parameters: ["page":"1","size":"20"]).responseJSON

这是我们开发中常见的设置请求方式,请求参数,这里的url支持多种数据类型,可以是String、URL、URLRequest等类型,为什么这么设计呢?因为在项目中可能当前我们跟前有一个String类型的连接,也有可能是个URL类型的连接,这时候在不需要转换的情况下就可以直接使用,方便快捷,更加灵活。

效果如下:

Alamofire.gif

三、URLSession

同样在Alamofire中也是对URLSession封装的,在OC中为NSURLSession,其实是一样的。一般网络请求分三个步骤:

1、设置URL请求地址
let url = URL.init(string: "协议://主机地址/路径/参数1&参数2")!
  • 协议:指定http协议还是https协议
  • 主机:即服务器地址ip地址或绑定ip的域名
  • 路径:项目在服务器上的位置
  • 参数:即get参数拼接在连接上
2、设置URLRequest属性
var request  = URLRequest.init(url: url)
request.httpMethod = HTTPMethod.post.rawValue
request.setValue("application/json", forHTTPHeaderField: "Content-Type")
let postData = ["username":"hibo","password":"123456"]
request.httpBody = try?JSONSerialization.data(withJSONObject: postData, options: [])
request.timeoutInterval = 30
request.cachePolicy = .useProtocolCachePolicy
  • httpMethod设置请求方式postget
  • setValue设置请求头信息
  • httpBody设置请求参数,参数打包在请求体中
  • timeoutInterval设置请求超时时间
  • cachePolicy设置网络请求缓存策略

通过以上的参数设置,能够感受到发送一次请求是多么不容易,因此网络请求是必须要被封装的

3、发起请求
URLSession.shared.dataTask(with: request) { (data, response, error) in
    print("*******网络请求*******")
    do {
        let list =  try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
        print(list)
    }catch{
        print(error)
    }
}.resume()
  • URLSession.shared为全局共享单例会话对象
  • 调用dataTask创建网络请求任务
  • resume默认为挂起状态,调用重新启动网络请求任务
  • data:请求到的数据流,通过JSONSerialization序列化为json格式使用

四、URLSessionConfiguration

URLSession.shared中内部已经配置了该项,此项为会话配置项,一般使用都会进行配置以适用于不同场景。查看该类如下:

open class var `default`: URLSessionConfiguration { get }
open class var ephemeral: URLSessionConfiguration { get }
@available(iOS 8.0, *)
open class func background(withIdentifier identifier: String) -> URLSessionConfiguration
  • default:默认模式,常用模式,在该模式下系统会创建持久化缓存,并在用户的钥匙串中保存证书
  • ephemeral:不支持持久性存储,所有内容的会随着session的生命周期结束而释放
  • background:与default模式类似,在该模式下会创建一个独立线程来传输网络请求数据,可以在后台乃至APP关闭的时候也可以进行数据传输

创建一个会话:

let configuration = URLSessionConfiguration.background(withIdentifier: "request_id")
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
session.dataTask(with: request) { (data, response, error) in
    print("*******网络请求*******")
    do {
        let list =  try JSONSerialization.jsonObject(with: data!, options: .allowFragments)
        print(list)
    }catch{
        print(error)
    }
}.resume()
  • 设置一个唯一会话标识,通过标识来区分不同的会话任务
  • 遵循URLSessionDelegate代理,实现代理方法,在本类中监控任务进度

下载任务:

let configuration = URLSessionConfiguration.background(withIdentifier: "request_id")
let session = URLSession.init(configuration: configuration, delegate: self, delegateQueue: OperationQueue.main)
session.downloadTask(with: url).resume()

注意在使用background模式时一定要开启后台下载权限,否则无法完成后台下载并回调数据。需要以下两步才能完成:

1、开启后台下载权限

var backgroundHandler: (()->Void)? = nil
//设置此处开启后台下载权限
func application(_ application: UIApplication, handleEventsForBackgroundURLSession identifier: String, completionHandler: @escaping () -> Void) {
    self.backgroundHandler = completionHandler
}

2、实现SessionDelegate代理方法,调用闭包方法,通知系统更新屏幕

func urlSessionDidFinishEvents(forBackgroundURLSession session: URLSession) {
    print("后台任务下载回来")
    DispatchQueue.main.async {
        guard let appDelegate = UIApplication.shared.delegate as? AppDelegate, let backgroundHandle = appDelegate.backgroundHandler else { return }
        backgroundHandle()
    }
}

苹果官方给出需要实现以上两个方法来完成后台下载,通知系统及时更新屏幕。官方文档

五、相关属性

官方文档

1、常规属性

  • identifier:配置对象的后台会话标识符
  • httpAdditionalHeaders:与请求一起发送的附加头文件字典
  • networkServiceType:网络服务的类型
  • allowsCellularAccess:一个布尔值,用于是否应通过蜂窝网络进行连接
  • timeoutIntervalForRequest:等待附加数据的超时时间
  • timeoutIntervalForResource:资源请求允许的最大时间范围
  • sharedContainerIdentifier:应将后台URL会话中的文件下载到的共享容器的标识符
  • waitsForConnectivity:一个布尔值,指示会话是否应等待连接变为可用还是立即失败

2、设置Cookie策略

  • httpCookieAcceptPolicy:决定何时接受cookie的策略常量
  • httpShouldSetCookies:一个布尔值,确定请求是否包含来自cookie存储区的cookie
  • httpCookieStorage:用于会话中存储cookiecookie存储区
  • HTTPCookie:该对象为不可变对象,从包含cookie属性的字典初始化,支持两个不同的cookie版本,v0、v1

3、设置安全策略

  • TLS协议:用于在两个通信应用程序之间提供保密性和数据完整性
  • tlsMaximumSupportedProtocol:在此会话中建立连接时客户端应请求的最大TLS协议版本
  • tlsMinimumSupportedProtocol:协议协商期间应接受的最小TLS协议
  • urlCredentialStorage:为身份验证提供凭据的凭据存储区

4、设置缓存策略

  • urlCache:用于为会话中的请求提供缓存响应的URL缓存
  • requestCachePolicy:决定何时从缓存中返回响应的预定义常量

5、支持后台转移

  • sessionSendsLaunchEvents:一个布尔值,指示当传输完成时,应用程序应在后台恢复还是启动
  • isDiscretionary:一个布尔值,用于确定后台任务是否可以由系统自行安排已获得最佳性能
  • shouldUseExtendedBackgroundIdleMode:一个布尔值,指示当应用程序转移到后台时是否应保持TCP连接打开

6、支持自定义协议

  • protocolClasses:在会话中处理请求的额外协议子类的数组
  • URLProtocol:该对象用来处理加载协议特定URL数据

7、支持多路径TCP

  • multipathServiceType:指定用于通过Wi-Fi和蜂窝接口传输数据的多路径TCP连接策略的服务类型

8、设置HTTP策略和代理属性

  • httpMaximumConnectionsPerHost:同时连接到给定主机的最大数量
  • httpShouldUsePipelining:一个布尔值,用于确定会话是否使用HTTP流水线
  • connectionProxyDictionary:包含相关要在此会话中使用的代理信息的字典

9、支持连接更改

  • waitsForConnectivity:一个布尔值,指示会话应等待连接可用还是立即失败

一个请求任务就有如此多的配置属性,可想而知对一个网络框架的整合,工作量也是非常大的。接下来我们就一步步来了解一下Alamofire是如何一步步整合的。

最后编辑于
©著作权归作者所有,转载或内容合作请联系作者
  • 序言:七十年代末,一起剥皮案震惊了整个滨河市,随后出现的几起案子,更是在滨河造成了极大的恐慌,老刑警刘岩,带你破解...
    沈念sama阅读 227,488评论 6 531
  • 序言:滨河连续发生了三起死亡事件,死亡现场离奇诡异,居然都是意外死亡,警方通过查阅死者的电脑和手机,发现死者居然都...
    沈念sama阅读 98,034评论 3 414
  • 文/潘晓璐 我一进店门,熙熙楼的掌柜王于贵愁眉苦脸地迎上来,“玉大人,你说我怎么就摊上这事。” “怎么了?”我有些...
    开封第一讲书人阅读 175,327评论 0 373
  • 文/不坏的土叔 我叫张陵,是天一观的道长。 经常有香客问我,道长,这世上最难降的妖魔是什么? 我笑而不...
    开封第一讲书人阅读 62,554评论 1 307
  • 正文 为了忘掉前任,我火速办了婚礼,结果婚礼上,老公的妹妹穿的比我还像新娘。我一直安慰自己,他们只是感情好,可当我...
    茶点故事阅读 71,337评论 6 404
  • 文/花漫 我一把揭开白布。 她就那样静静地躺着,像睡着了一般。 火红的嫁衣衬着肌肤如雪。 梳的纹丝不乱的头发上,一...
    开封第一讲书人阅读 54,883评论 1 321
  • 那天,我揣着相机与录音,去河边找鬼。 笑死,一个胖子当着我的面吹牛,可吹牛的内容都是我干的。 我是一名探鬼主播,决...
    沈念sama阅读 42,975评论 3 439
  • 文/苍兰香墨 我猛地睁开眼,长吁一口气:“原来是场噩梦啊……” “哼!你这毒妇竟也来了?” 一声冷哼从身侧响起,我...
    开封第一讲书人阅读 42,114评论 0 286
  • 序言:老挝万荣一对情侣失踪,失踪者是张志新(化名)和其女友刘颖,没想到半个月后,有当地人在树林里发现了一具尸体,经...
    沈念sama阅读 48,625评论 1 332
  • 正文 独居荒郊野岭守林人离奇死亡,尸身上长有42处带血的脓包…… 初始之章·张勋 以下内容为张勋视角 年9月15日...
    茶点故事阅读 40,555评论 3 354
  • 正文 我和宋清朗相恋三年,在试婚纱的时候发现自己被绿了。 大学时的朋友给我发了我未婚夫和他白月光在一起吃饭的照片。...
    茶点故事阅读 42,737评论 1 369
  • 序言:一个原本活蹦乱跳的男人离奇死亡,死状恐怖,灵堂内的尸体忽然破棺而出,到底是诈尸还是另有隐情,我是刑警宁泽,带...
    沈念sama阅读 38,244评论 5 355
  • 正文 年R本政府宣布,位于F岛的核电站,受9级特大地震影响,放射性物质发生泄漏。R本人自食恶果不足惜,却给世界环境...
    茶点故事阅读 43,973评论 3 345
  • 文/蒙蒙 一、第九天 我趴在偏房一处隐蔽的房顶上张望。 院中可真热闹,春花似锦、人声如沸。这庄子的主人今日做“春日...
    开封第一讲书人阅读 34,362评论 0 25
  • 文/苍兰香墨 我抬头看了看天上的太阳。三九已至,却和暖如春,着一层夹袄步出监牢的瞬间,已是汗流浃背。 一阵脚步声响...
    开封第一讲书人阅读 35,615评论 1 280
  • 我被黑心中介骗来泰国打工, 没想到刚下飞机就差点儿被人妖公主榨干…… 1. 我叫王不留,地道东北人。 一个月前我还...
    沈念sama阅读 51,343评论 3 390
  • 正文 我出身青楼,却偏偏与公主长得像,于是被迫代替她去往敌国和亲。 传闻我的和亲对象是个残疾皇子,可洞房花烛夜当晚...
    茶点故事阅读 47,699评论 2 370