<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
到目前為止,我們已經看了一個簡單的Request/Response的結構體和實現。接下來,我們來討論一下傳送請求和接收響應。
如果我們回想一下第一節,我們會用HTTP回撥給他,我們傳送了一個請求,並且最終得到了一個響應(忽略Error)沒有任何“任務”或者代理亦或其他什麼東西。我們傳送(或載入)一個請求,最終都會得到一個響應。
如果我們用一個方法來描述那個功能,那麼這個方法如下所示
func load(request: HTTPRequest, completion: @escaping (HTTPResponse) -> Void)
我們傳送了一個請求,在未來的某個節點,閉包將會被執行,表裡涵蓋的是我們要的響應。當然,單個方法並不是我們想要的;換句話說,我們想要表述的是一個介面。所以,我們會把他封裝進一個protocol中:
public protocol HTTPLoading { func load(request: HTTPRequest, completion: @escaping (HTTPResponse) -> Void) }
當然,我們可能會得到一個error響應。所以,我們要用自己的“results”重新命名(typealiase)來替換HTTPResponse:
func load(request: HTTPRequest, completion: @escaping (HTTPResult) -> Void)
讓我們停下來欣賞一下。 這個方法就是我們定義網路框架的核心功能所需要的全部。 就是這樣:一個方法。 棒極了。
URLSession
就像“路上的橡膠”,這是在我們的請求通過空中(或有線)傳送到我們指定的伺服器之前需要清除的最後一個障礙。 因此,我們在 URLSession
上實現 HTTPLoading
是為了將 HTTPRequest
轉換為對談需要的 URLRequest
,這是有道理的:
extension URLSession: HTTPLoading { public func load(request: HTTPRequest, completion: @escaping (HTTPResult) -> Void) guard let url = request.url else { // we couldn't construct a proper URL out of the request's URLComponents completion(.failure(...)) return } // construct the URLRequest var urlRequest = URLRequest(url: url) urlRequest.httpMethod = request.method.rawValue // copy over any custom HTTP headers for (header, value) in request.headers { urlRequest.addValue(value, forHTTPHeaderField: header) } if request.body.isEmpty == false { // if our body defines additional headers, add them for (header, value) in request.body.additionalHeaders { urlRequest.addValue(value, forHTTPHeaderField: header) } // attempt to retrieve the body data do { urlRequest.httpBody = try request.body.encode() } catch { // something went wrong creating the body; stop and report back completion(.failure(...)) return } } let dataTask = session.dataTask(with: urlRequest) { (data, response, error) in // construct a Result<HTTPResponse, HTTPError> out of the triplet of data, url response, and url error let result = HTTPResult(request: request, responseData: data, response: response, error: error) completion(result) } // off we go! dataTask.resume() } }
這應該很容易理解。 我們正在執行從 HTTPRequest
值中提取資訊並將其應用於 URLRequest
的步驟。 如果在任何時候出現問題,那麼我們將報告錯誤。 (您需要自己填寫 ... 部分以構造適當的 HTTPError
值)
假設構建一切順利,我們最終會得到一個 URLRequest
,我們可以將其轉換為 URLSessionDataTask
並執行它。 當它完成時,我們將獲取響應值,將它們轉換為 HTTPResult
,並通過完成塊報告回來。
在傳輸過程中的任何時候,我們的請求都可能失敗。 如果我們處於飛航模式或其他“未連線”狀態,則請求可能永遠不會傳送。 如果我們正在傳送請求(在我們得到響應之前),網路連線可能會斷開。 或者它可能會在我們傳送後但在我們收到回覆之前掉線。 或者它可能會在我們開始收到響應之後但在完全接收到響應之前下降。
這就是我們在定義請求和響應型別時建立 HTTPError
結構的原因,這意味著我們需要更加努力地構建我們的結果,而不是簡單地檢查“我是否得到了一些資料”。
在高層次上,初始化 HTTPResult
的邏輯大致如下所示:
var httpResponse: HTTPResponse? if let r = response as? HTTPURLResponse { httpResponse = HTTPResponse(request: request, response: r, body: responseData ?? Data()) } if let e = error as? URLError { let code: HTTPError.Code switch e.code { case .badURL: code = .invalidRequest case .unsupportedURL: code = ... case .cannotFindHost: code = ... ... default: code = .unknown } self = .failure(HTTPError(code: code, request: request, response: httpResponse, underlyingError: e)) } else if let someError = error { // an error, but not a URL error self = .failure(HTTPError(code: .unknown, request: request, response: httpResponse, underlyingError: someError)) } else if let r = httpResponse { // not an error, and an HTTPURLResponse self = .success(r) } else { // not an error, but also not an HTTPURLResponse self = .failure(HTTPError(code: .invalidResponse, request: request, response: nil, underlyingError: error)) }
HTTPLoading 使用方法:
public class StarWarsAPI { private let loader: HTTPLoading = URLSession.shared public func requestPeople(completion: @escaping (...) -> Void) { var r = HTTPRequest() r.host = "swapi.dev" r.path = "/api/people" loader.load(request: r) { result in // TODO: interpret the result completion(...) } } }
我想在這裡指出,我們在任何時候都不會解釋Response的狀態程式碼。 獲得 500 Internal Server Error
或 404 Not Found
響應是成功的響應。 在這一層,“成功”意味著“我們得到了迴應”,而不是“迴應表明某種語意錯誤”。 解釋狀態程式碼是特定於應用程式的邏輯。 在未來的貼文中,我們將允許基於狀態程式碼的可客製化的、特定於應用程式的行為(例如跟隨重定向或重試請求)。
我們定義的這個單一方法看似簡單,但也不完整。 我們還沒有指出任何主動取消請求的方法,我們需要調整我們的 HTTPLoading
協定以新增更多功能。 我們還將把它從協定轉換為類,原因我將在以後的貼文中解釋。
儘管存在這些小漏洞,該協定在其簡單性方面仍然很漂亮,它展示了一個好的問題概念化如何能夠產生強大而美麗的東西。
簡單是最終的複雜。
在下一篇文章中,我們將研究使用 HTTPLoading
協定來簡化單元測試。
以上就是Swift HTTP載入請求Loading Requests教學的詳細內容,更多關於Swift HTTP載入請求的資料請關注it145.com其它相關文章!
相關文章
<em>Mac</em>Book项目 2009年学校开始实施<em>Mac</em>Book项目,所有师生配备一本<em>Mac</em>Book,并同步更新了校园无线网络。学校每周进行电脑技术更新,每月发送技术支持资料,极大改变了教学及学习方式。因此2011
2021-06-01 09:32:01
综合看Anker超能充系列的性价比很高,并且与不仅和iPhone12/苹果<em>Mac</em>Book很配,而且适合多设备充电需求的日常使用或差旅场景,不管是安卓还是Switch同样也能用得上它,希望这次分享能给准备购入充电器的小伙伴们有所
2021-06-01 09:31:42
除了L4WUDU与吴亦凡已经多次共事,成为了明面上的厂牌成员,吴亦凡还曾带领20XXCLUB全队参加2020年的一场音乐节,这也是20XXCLUB首次全员合照,王嗣尧Turbo、陈彦希Regi、<em>Mac</em> Ova Seas、林渝植等人全部出场。然而让
2021-06-01 09:31:34
目前应用IPFS的机构:1 谷歌<em>浏览器</em>支持IPFS分布式协议 2 万维网 (历史档案博物馆)数据库 3 火狐<em>浏览器</em>支持 IPFS分布式协议 4 EOS 等数字货币数据存储 5 美国国会图书馆,历史资料永久保存在 IPFS 6 加
2021-06-01 09:31:24
开拓者的车机是兼容苹果和<em>安卓</em>,虽然我不怎么用,但确实兼顾了我家人的很多需求:副驾的门板还配有解锁开关,有的时候老婆开车,下车的时候偶尔会忘记解锁,我在副驾驶可以自己开门:第二排设计很好,不仅配置了一个很大的
2021-06-01 09:30:48
不仅是<em>安卓</em>手机,苹果手机的降价力度也是前所未有了,iPhone12也“跳水价”了,发布价是6799元,如今已经跌至5308元,降价幅度超过1400元,最新定价确认了。iPhone12是苹果首款5G手机,同时也是全球首款5nm芯片的智能机,它
2021-06-01 09:30:45