Swift-URLSession基础(一)

写点东西开篇不配个图,好像缺点啥。。。有些东西我们天天见,但是用专业术语不一定能表达,以下是专业表达。


惠民专属
URLSession

URLSession:苹果关方给出对解释是:(An object that coordinates a group of related network data transfer tasks.)
即:协调一组相关网络数据传输任务的对象。

我们可以通俗的理解成类似于一个协调各个网络数据任务的管理者。其在iOS7+系统适用,隶属Foundation框架。

The URLSession class and related classes provide an API for downloading data from and uploading data to endpoints indicated by URLs. The API also enables your app to perform background downloads when your app isn’t running or, in iOS, while your app is suspended. A rich set of delegate methods support authentication and allow your app to be notified of events like redirection.

译文:URLSession类和相关类提供了一个API,用于从url指示的端点下载数据并将数据上载到该端点。该API还使您的应用程序能够在应用程序未运行时执行后台下载,或者在iOS中,在应用程序挂起时执行后台下载。一组丰富的委托方法支持身份验证,并允许应用程序收到重定向等事件的通知。

@available(iOS 7.0, *)
open class URLSession : NSObject

我们在进行网络数据处理的时候怎么使用呢?
使用使用URLSession的一般格式:

//1、创建URL
let url: URL = URL(string: "http://study.teacheredu.cn/proj/proj/tlogin/mobile/v440/CategoryCourse/gpCategoryCourse.json?ptcode=34101&projectId=6355&userId=698667&stageId=0")!
        
//2、创建URLRequest
let request: URLRequest = URLRequest(url: url)
        
//3、创建URLSession
let configration = URLSessionConfiguration.default
let session =  URLSession(configuration: configration)

//4、URLSessionTask子类
let task: URLSessionDataTask = session.dataTask(with: request) { (data, response, error) in
            if error == nil {
                do {
                    let result: NSDictionary = try JSONSerialization.jsonObject(with: data!, options: JSONSerialization.ReadingOptions.allowFragments) as! NSDictionary
                    print(result)
                    DispatchQueue.main.async {
                        let message: NSDictionary = result.object(forKey: "othermapper") as! NSDictionary
                        let name = message.object(forKey: "name") as? String
                        print(name as Any)
                        self.textLabel.text = name
                    }
                }catch{
                    
                }
          }
}
        
//5、启动任务
task.resume()

同样的还有更简化的写法:

        //使用格式2
        URLSession.shared.dataTask(with: url) { (data, response, error) in
            
            if error == nil {
                print("网络请求成功")
            }
            
        }.resume()
        
        
        //使用格式2
        URLSession.shared.dataTask(with: request) { (data, response, error) in
            
            if error == nil {
                print("网络请求成功")
            }
            
        }.resume()

resume()方法的作用是开启任务,执行完成之后会走闭包。
下面我们就针对URLSession类中所包含的一些基本属性和函数作简要分析。

open class var shared: URLSession { get }

//提供了一个共享的单例会话对象

public /*not inherited*/ init(configuration: URLSessionConfiguration)
public /*not inherited*/ init(configuration: URLSessionConfiguration, delegate: URLSessionDelegate?, delegateQueue queue: OperationQueue?)

//初始化方法

open var delegateQueue: OperationQueue { get }
open var delegate: URLSessionDelegate? { get }

//OperationQueue代理和URLSessionDelegate代理

dataTask创建一个网络会话数据任务。

@NSCopying open var configuration: URLSessionConfiguration { get }

//URLSession的配置模式
在这里我们要重点提一下configuration,其实它也是我们在使用的时候容易被忽视的。

URLSessionConfiguration

URLSessionConfiguration的初始化会涉及三种配置模式:

    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:默认模式,通常我们用这种模式就足够了。default模式下系统会创建一个持久化的缓存并在用户的钥匙串中存储证书。

ephemeral:系统没有任何持久性存储,所有内容的生命周期都与session相同,当session无效时,所有内容自动释放。

background:创建一个可以在后台甚至APP已经关闭的时候仍然在传输数据的会话。background模式与default模式非常相似,不过background模式会用一个独立线程来进行数据传输。background模式可以在程序挂起,退出,崩溃的情况下运行task。也可以利用标识符来恢复进。注意,后台Session一定要在创建的时候赋予一个唯一的identifier,这样在APP下次运行的时候,能够根据identifier来进行相关的区分。如果用户关闭了APP,IOS 系统会关闭所有的background Session。而且,被用户强制关闭了以后,IOS系统不会主动唤醒APP,只有用户下次启动了APP,数据传输才会继续。

我们来看下面两个简单的事例:
事例1:

let config1 = URLSessionConfiguration.default
let config2 = URLSessionConfiguration.ephemeral
print("沙盒size:\(String(describing: config1.urlCache?.diskCapacity))")
print("内存size:\(String(describing: config1.urlCache?.memoryCapacity))")
print("沙盒size:\(String(describing: config2.urlCache?.diskCapacity))")
print("内存size:\(String(describing: config2.urlCache?.memoryCapacity))")
打印结果

由以上我们可以知道default和ephemeral模式下系统所分配的内存大小是一样的,但是ephemeral模式下系统所分配的持久化的缓存为0. 大多数情况下我们使用的时候直接用default模式就OK。
事例2:

//初始化一个后台的模式的会话配置
let config3 = URLSessionConfiguration.background(withIdentifier: "backgroundTest")

//初始化session会话
let session = URLSession.init(configuration: config3, delegate: self as URLSessionDelegate , delegateQueue: .main)

//方式1
session.downloadTask(with: url)

//方式2(闭包回调)
//session.downloadTask(with: url) { (url, response, error) in
//}.resume()

以上代码根据一个url建立一个下载会话,我们在URLSession的初始化方法中设置了delegate为self,需要实现URLSessionDownloadDelegate。而
URLSessionDownloadDelegate中包括一下几个方法:

public protocol URLSessionDownloadDelegate : URLSessionTaskDelegate {

    下载完成之后就回调(Tells the delegate that a download task has finished downloading.)
    @available(iOS 7.0, *)
    func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL)

    下载进度监控(Periodically informs the delegate about the download’s progress.)
    @available(iOS 7.0, *)
    optional func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didWriteData bytesWritten: Int64, totalBytesWritten: Int64, totalBytesExpectedToWrite: Int64)

    下载任务已恢复下载(Tells the delegate that the download task has resumed downloading.)
    @available(iOS 7.0, *)
    optional func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didResumeAtOffset fileOffset: Int64, expectedTotalBytes: Int64)
}

实现以上几个代理方法还不能够完成后台的下载功能,还需要下面两个步骤:
1、在AppDelegate中作如下处理:


Appdelegate

这个方法的进一步的官方解释如下:


我爱中文,学英文纯属工作需要

2、会话代理中


delegate实现方法

URLSessionConfiguration常用属性:

open var identifier: String? { get } //配置对象的后台会话标识符。

open var requestCachePolicy: NSURLRequest.CachePolicy 一个预定义常量,用于确定何时从缓存中返回响应

open var timeoutIntervalForRequest: TimeInterval 等待其他数据时使用的超时间隔。

open var timeoutIntervalForResource: TimeInterval 资源请求应该允许的最大时间量。

open var networkServiceType: NSURLRequest.NetworkServiceType网络服务的类型

open var allowsCellularAccess: Bool 一个布尔值,用于确定是否应通过蜂窝网络进行连接。

@available(iOS 13.0, *)
open var allowsExpensiveNetworkAccess: Bool  //允许高成本的网络访问

@available(iOS 13.0, *)
 open var allowsConstrainedNetworkAccess: Bool  //允许强约束的网络访问

@available(iOS 11.0, *)
open var waitsForConnectivity: Bool 一个布尔值,指示会话是否应等待连接变为可用或者立即失败

@available(iOS 7.0, *)
open var isDiscretionary: Bool  一个布尔值,用于确定后台任务是否可以由系统自行调度以获得最佳性能。

@available(iOS 8.0, *)
open var sharedContainerIdentifier: String? 应该下载后台URL会话中的文件的共享容器的标识符。

@available(iOS 7.0, *)
open var sessionSendsLaunchEvents: Bool 一个布尔值,指示传输完成后是否应在后台继续或启动应用程序
    
open var connectionProxyDictionary: [AnyHashable : Any]?包含要在此会话中使用的代理的信息的字典。

open var httpShouldSetCookies: Bool 一个布尔值,用于确定请求是否应包含来自cookie存储区的cookie
    
open var httpCookieAcceptPolicy: HTTPCookie.AcceptPolicy  一种政策常数,当Cookie被接受时决定。 

open var httpAdditionalHeaders: [AnyHashable : Any]? 与请求一起发送的附加头文件的字典。

open var httpMaximumConnectionsPerHost: Int  对给定主机进行的同时连接的最大数目。 

open var httpCookieStorage: HTTPCookieStorage?  管理cookies存储的容器

open var urlCredentialStorage: URLCredentialStorage? 凭据存储的容器

open var urlCache: URLCache? 将URL请求映射到缓存响应对象的对象

@available(iOS 9.0, *)
open var shouldUseExtendedBackgroundIdleMode: Bool 一个布尔值,指示应用程序移到后台时是否应保持TCP连接打开。

open var protocolClasses: [AnyClass]?   在会话中处理请求的额外协议子类的数组。 

@available(iOS 11.0, *)
open var multipathServiceType: URLSessionConfiguration.MultipathServiceType  一种服务类型,具体规定了无线FI和蜂窝接口上的多个TCP连接政策。 
CachePolicy

和Objective-C一样,Swift对于NSURLRequest.CachePolicy缓存策略有以下定义


CachePolicy
  • case useProtocolCachePolicy //默认缓存策略 如果一个NSCachedURLResponse对于请求并不存在,数据将会从源端获取。如果请求拥有一个缓存的响应,那么URL加载系统会检查这个响应来决定,如果它指定内容必须重新生效的话。假如内容必须重新生效,将建立一个连向源端的连接来查看内容是否发生变化。假如内容没有变化,那么响应就从本地缓存返回数据。如果内容变化了,那么数据将从源端获取

  • case reloadIgnoringLocalCacheData //URL应该加载源端数据,不使用本地缓存数据

  • case reloadIgnoringLocalAndRemoteCacheData //本地缓存数据、代理和其他中介都要忽视他们的缓存,直接加载源数据

  • public static var reloadIgnoringCacheData: NSURLRequest.CachePolicy { get }//reloadIgnoringLocalCacheData

  • case returnCacheDataElseLoad //指定已存的缓存数据应该用来响应请求,不管它的生命时长和过期时间。如果在缓存中没有已存数据来响应请求的话,数据从源端加载

  • case returnCacheDataDontLoad //指定已存的缓存数据用来满足请求,不管生命时长和过期时间。如果在缓存中没有已存数据来响应URL加载请求的话,不去尝试从源段加载数据,此时认为加载请求失败。这个常量指定了一个类似于离线模式的行为

  • case reloadRevalidatingCacheData //指定如果已存的缓存数据被提供它的源段确认为有效则允许使用缓存数据响应请求,否则从源段加载数据。

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