Swift-URLSession基础(一)

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


Swift-URLSession基础(一)_第1张图片
惠民专属
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))")
Swift-URLSession基础(一)_第2张图片
打印结果

由以上我们可以知道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中作如下处理:


Swift-URLSession基础(一)_第3张图片
Appdelegate

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


Swift-URLSession基础(一)_第4张图片
我爱中文,学英文纯属工作需要

2、会话代理中


Swift-URLSession基础(一)_第5张图片
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缓存策略有以下定义


Swift-URLSession基础(一)_第6张图片
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 //指定如果已存的缓存数据被提供它的源段确认为有效则允许使用缓存数据响应请求,否则从源段加载数据。

Swift-URLSession基础(一)_第7张图片
三哥

你可能感兴趣的:(Swift-URLSession基础(一))