之前我们看完了Alamofire.request
的函数签名, 接下来, 我们来看看里面的实现
Alamofire.request
request 函数签名
request 函数实现
先来贴一下代码
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
)
}
可以看到, 这个方法其实只是简单的调用SessionManager.default.request
而已.
这里, 出现了一个新的类型, SessionManager
和 返回值 DataRequest
我们下面先看看看 SessionManager
SessionManager
SessionManager
负责创建和管理请求, 并且在内部也管理了一个 URLSession 对象.
为了理解这个类型, 我们先来看看, 如果使用原生的 URLSession
该怎么写代码
var data: Data?
override func viewDidLoad() {
super.viewDidLoad()
let session = URLSession(configuration: .default, delegate: self, delegateQueue: nil)
let dataTask = session.dataTask(with: URL(string: "https://httpbin.org/get")!)
dataTask.resume()
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive response: URLResponse, completionHandler: @escaping (URLSession.ResponseDisposition) -> Void) {
self.data = Data()
completionHandler(.allow)
}
func urlSession(_ session: URLSession, dataTask: URLSessionDataTask, didReceive data: Data) {
self.data?.append(data)
}
func urlSession(_ session: URLSession, task: URLSessionTask, didCompleteWithError error: Error?) {
if let data = self.data, let string = String(data: data, encoding: String.Encoding.utf8) {
print(string)
}
}
可以看到, 整个流程就是首先创建一个 session, 然后使用这个 session 创建一个 dataTask, 最后启动任务, 就可以在代理中获取到数据.
看到这里, 我们再看看之前的代码
SessionManager.default
可以看到, 我们是通过这种方式, 创建的一个 SessionManager
先看看 default
这个属性.
open static let `default`: SessionManager = {
let configuration = URLSessionConfiguration.default
configuration.httpAdditionalHeaders = SessionManager.defaultHTTPHeaders
return SessionManager(configuration: configuration)
}()
可以看到, 这里是使用默认的URLSessionConfiguration 配置, 并在里面添加了一些请求头. 并使用这个配置初始化SessionManager
.
既然这里有一个默认的请求头, 我们就来看看添加了哪些东西
open static let defaultHTTPHeaders: HTTPHeaders = {
// 设置编码类型(gzip)
// Accept-Encoding HTTP Header; see https://tools.ietf.org/html/rfc7230#section-4.2.3
let acceptEncoding: String = "gzip;q=1.0, compress;q=0.5"
// 设置语言
// Accept-Language HTTP Header; see https://tools.ietf.org/html/rfc7231#section-5.3.5
let acceptLanguage = Locale.preferredLanguages.prefix(6).enumerated().map { index, languageCode in
let quality = 1.0 - (Double(index) * 0.1)
return "\(languageCode);q=\(quality)"
}.joined(separator: ", ")
// 设置 ua
// User-Agent Header; see https://tools.ietf.org/html/rfc7231#section-5.5.3
// Example: `iOS Example/1.0 (org.alamofire.iOS-Example; build:1; iOS 10.0.0) Alamofire/4.0.0`
let userAgent: String = {
if let info = Bundle.main.infoDictionary {
let executable = info[kCFBundleExecutableKey as String] as? String ?? "Unknown"
let bundle = info[kCFBundleIdentifierKey as String] as? String ?? "Unknown"
let appVersion = info["CFBundleShortVersionString"] as? String ?? "Unknown"
let appBuild = info[kCFBundleVersionKey as String] as? String ?? "Unknown"
let osNameVersion: String = {
let version = ProcessInfo.processInfo.operatingSystemVersion
let versionString = "\(version.majorVersion).\(version.minorVersion).\(version.patchVersion)"
let osName: String = {
#if os(iOS)
return "iOS"
.... 其他系统类型
#endif
}()
return "\(osName) \(versionString)"
}()
let alamofireVersion: String = {
guard
let afInfo = Bundle(for: SessionManager.self).infoDictionary,
let build = afInfo["CFBundleShortVersionString"]
else { return "Unknown" }
return "Alamofire/\(build)"
}()
return "\(executable)/\(appVersion) (\(bundle); build:\(appBuild); \(osNameVersion)) \(alamofireVersion)"
}
return "Alamofire"
}()
可以看到, 主要是添加了Accept-Encoding
, Accept-Language
, User-Agent
这几个请求头.
接下来, 我们看看这个类的构造函数, 其实有两个构造函数, 不过我们这里用到的是这一个.
public init(
configuration: URLSessionConfiguration = URLSessionConfiguration.default,
delegate: SessionDelegate = SessionDelegate(),
serverTrustPolicyManager: ServerTrustPolicyManager? = nil)
{
self.delegate = delegate
self.session = URLSession(configuration: configuration, delegate: delegate, delegateQueue: nil)
commonInit(serverTrustPolicyManager: serverTrustPolicyManager)
}
可以看到, 这里除了configuration
这个参数外, 还有一个 delegate
和 serverTrustPolicyManager
delegate
主要是起到一个接受事件, 以及处理数据的作用. 跟我们写原生的类似. Alamofire 将代理单独分到独立的类中处理, 并在有在其中将所有的代理回调, 以闭包属性的方式暴露出来, 方便用户自行处理事件. 具体的, 我们后面再细讲, 这里先大致了解一下.
而serverTrustPolicyManager
则主要是为了处理证书.
函数的主体中, 我们看到, 这里跟我们写原生代码一样, 创建了一个 URLSession, 并将之前创建的代理类作为代理.
接下来, 调用了一个 commonInit
方法继续完成初始化.
commonInit
里面并没有什么特别的东西, 这里就略过了.