前言
最近在做Swift3遷移工作的時候,遇到了一個很尷尬的事情,Alamofire的庫最低支持iOS 9.0了,可是我們的項(xiàng)目必須支持iOS 8.0+,本著不重復(fù)造輪子的想法,于是我決定換一個輕量級的網(wǎng)絡(luò)加載庫Just
原文地址
Talk is cheap, show me the code!
請求方式
Just支持的請求方式有:
DELETE
GET
HEAD
OPTIONS
PATCH
POST
PUT
同步請求\異步請求
Just支持同步請求和異步請求,Alamofre支持異步請求,不過我們平時開發(fā)中大多數(shù)請求也都是異步完成的
當(dāng)我們用Swift開發(fā)時,我們傾向于避開同步網(wǎng)絡(luò)請求,因?yàn)橥秸埱髸枞骶€程,這將影響Cocoa/Cocoa Touch應(yīng)用程序刷新UI。然而,使用同步請求也沒有什么inherantly立膛。事實(shí)上,同步的代碼通常更容易理解揪罕。
// 發(fā)起一個同步請求
var r = Just.get("http://httpbin.org/get", params:["page": 3])
// … "r" becomes available here
想變成異步請求也是非常簡單的
// 發(fā)起一個異步請求
Just.get("http://httpbin.org/get", params:["page": 3]) { (r) in
// the same "r" is available asynchronously here
}
但是需要注意的是異步請求的callback是不運(yùn)行在主線程的因此我們?nèi)绻朐赾allback中刷新UI必須自己使用GCD或者NSOperationQueue來回到主線程
HTTP REQUEST
雖然上面的簡單的例子都是調(diào)用具體的get/post請求方法 但是這些方法最終還是調(diào)用 JustAdaptor 的方法,JustAdaptor是個protocol 這就體現(xiàn)了Swift面向協(xié)議開發(fā)的強(qiáng)大之處.
Show the code:
public protocol JustAdaptor {
func request(
_ method: HTTPMethod, // 請求方式
URLString: String, // 請求地址
params: [String: Any], // 請求參數(shù) 使用字典樣式
data: [String: Any], // 請求參數(shù) 例如 表單數(shù)據(jù)
json: Any?, // 請求參數(shù)
headers: [String: String], // 請求頭信息 字典樣式
files: [String: HTTPFile], // 上傳文件
auth: Credentials?, // 認(rèn)證信息
cookies: [String: String], // 請求cookie
redirects: Bool, // 是否允許重定向
timeout: Double?, // 超時時間
URLQuery: String?, //
requestBody: Data?, // 請求體
asyncProgressHandler: TaskProgressHandler?, // 進(jìn)度操作 用于做上傳或下載的進(jìn)度
asyncCompletionHandler: ((HTTPResult) -> Void)? // 完成操作 所有的服務(wù)器返回信息包在HTTPResult對象中
) -> HTTPResult
init(session: URLSession?, defaults: JustSessionDefaults?)
}
簡單的請求
GET請求
一個簡單的get請求:
// 無參數(shù)
Just.get("http://httpbin.org/get"){ (r) in
// 異步請求結(jié)果
}
// 帶參數(shù)
Just.get("http://httpbin.org/get", params:["page": 3]) { (r) in
// 異步請求結(jié)果
}
POST請求
一個簡單的post請求:
Just.post("http://httpbin.org/post") { (r) in
// 異步請求結(jié)果
}
還有很多別的請求方式就不在一一贅述.
取消請求
有開啟請求自然也有取消請求方法
r.cancel()
更復(fù)雜的請求
如果想發(fā)送表單數(shù)據(jù),可以用data
參數(shù):
// 請求體會變成firstName=Barry&lastName=Allen
// Content-Type頭信息將加入application/x-form-www-encoded
Just.post("http://httpbin.org/post", data:["firstName":"Barry","lastName":"Allen"])
JSON數(shù)據(jù)也是一樣的
// 請求體是JSON encoded
// Content-Type頭信息呢是'application/json'
Just.post("http://httpbin.org/post", json:["firstName":"Barry","lastName":"Allen"])
Redirect
默認(rèn)情況下,Just會遵循服務(wù)器的redirect設(shè)置,你也可以用allowRedirect控制這種行為
// redirects
Just.get("http://httpbin.org/redirect/2").isRedirect // false
// no redirects
Just.get("http://httpbin.org/redirect/2", allowRedirects:false).isRedirect // true
此外, 你也可以設(shè)置永久redirect
// permanent redirect
Just.get("http://httpbin.org/status/301", allowRedirects:false).isPermanentRedirect // true
// non permanent redirect
Just.get("http://httpbin.org/status/302", allowRedirects:false).isPermanentRedirect // false
FILES
用Just上傳文件也是很簡單的
import Foundation
let elonPhotoURL = Bundle.main.url(forResource: "elon", withExtension: "jpg")!
let uploadResult = Just.post("http://httpbin.org/post", files:["elon": .url(elonPhotoURL, nil)]) // <== that's it
print(uploadResult.text ?? "")
在這里梯码,文件是用一個NSURL指定。 或者好啰,一個文件可以是操作文件數(shù)據(jù)或只是一個字符串轩娶。但是在這兩種情況下,需要一個文件名框往。
let someData = "Marco".data(using: String.Encoding.utf8)!
if let text = Just.post(
"http://httpbin.org/post",
files:[
"a":.data("marco.text", someData, nil), //一個 Data類型文件
"b":.text("polo.txt", "Polo", nil) // 一個 String類型文件
]
).text {
print(text)
}
還可以這樣;
if let json = Just.post(
"http://httpbin.org/post",
data:["lastName":"Musk"], // 參數(shù)
files:["elon":.url(elonPhotoURL, nil)] // 文件
).json as? [String:AnyObject] {
print(json["form"] ?? [:]) // lastName:Musk
print(json["files"] ?? [:]) // elon
}
LINK HEADERS
許多HTTP api鏈接頭,增加api的自我描述
例如 Github分頁功能API就是這樣:
let gh = Just.head("https://api.github.com/users/dduan/repos?page=1&per_page=5")
gh.headers["link"]
// <https://api.github.com/user/75067/repos?page=2&per_page=5>; rel="next", <https://api.github.com/user/75067/repos?page=9&per_page=5>; rel="last"
Just對于解析link headers更容易:
gh.links["next"] // ["rel": "next", "url":"https://api.github.com/user/75067/repos?page=2&per_page=5"]
gh.links["last"] // ["rel": "last", "url":"https://api.github.com/user/75067/repos?page=9&per_page=5"]
COOKIE
如果你希望服務(wù)器返回cookie可以這么做:
// returns an NSHTTPCookie
Just.get("http://httpbin.org/cookies/set/name/elon", allowRedirects:false).cookies["name"]
發(fā)起一個帶著cookie的請求
Just.get("http://httpbin.org/cookies", cookies:["test":"just"]) // ok
AUTHENTICATION
如果請求是受到基本身份驗(yàn)證或摘要式身份驗(yàn)證鳄抒,請使用身份驗(yàn)證參數(shù)元組提供用戶名和密碼
Just.get("http://httpbin.org/basic-auth/flash/allen", auth:("flash", "allen")) // ok
TIMEOUT
你也可以設(shè)置超時時間
Just.get("http://httpbin.org/delay/5", timeout:0.2).reason
UPLOAD AND DOWNLOAD PROGRESS
上傳和下載文件也是很簡單
Just.post(
"http://httpbin.org/post",
files:["large file":.text("or", "pretend this is a large file", nil)],
asyncProgressHandler: { p in
p.type // 方式 .Upload or .Download
p.bytesProcessed // 當(dāng)前大小
p.bytesExpectedToProcess // 總大小
p.percent // 百分比
}
) { r in
// finished
}
CUSTOMIZATION / ADVANCED USAGE
如果你想改變Just的一些默認(rèn)設(shè)置,需要使用JustSessionDefaults
自定義寫個性化設(shè)置
let myJustDefaults = JustSessionDefaults(
// NSJSONSerialization reading options
JSONReadingOptions: .mutableContainers,
// NSJSONSerialization writing options
JSONWritingOptions: .prettyPrinted,
// 每個請求的頭信息
headers: ["OH":"MY"],
// 多部分post請求邊界
multipartBoundary: "Ju5tH77P15Aw350m3",
// NSURLCredential持久性選項(xiàng)
credentialPersistence: .none,
// en(de)coding for HTTP body
encoding: String.Encoding.utf8
)
使用:
let just = JustOf<HTTP>(defaults: myJustDefaults)
just.post("http://httpbin.org/post").request?.allHTTPHeaderFields?["OH"] ?? ""
HTTP RESULT
HTTP請求的結(jié)果被放在一個單一的對象
Show the code:
public final class HTTPResult : NSObject {
public final var content: Data?
public var response: URLResponse?
public var error: Error?
public var request: URLRequest? { return task?.originalRequest }
public var task: URLSessionTask?
public var encoding = String.Encoding.utf8
public var JSONReadingOptions = JSONSerialization.ReadingOptions(rawValue: 0)
public var ok: Bool {
return statusCode != nil && !(statusCode! >= 400 && statusCode! < 600)
}
public var json: Any? {
return content.flatMap {
try? JSONSerialization.jsonObject(with: $0, options: JSONReadingOptions)
}
}
public var statusCode: Int? {
return (self.response as? HTTPURLResponse)?.statusCode
}
......
判斷請求是否成功可以用ok或者statusCode兩個屬性
r.ok
r.statusCode
其他描述:
// 服務(wù)器返回?cái)?shù)據(jù)
r.headers // response headers
r.content // response body as NSData?
r.text // response body as text?
r.json // response body parsed by NSJSONSerielization
r.url // the URL, as URL
r.isRedirect // is this a redirect response
總結(jié)
由于本人學(xué)識短淺,文章有錯誤的地方還望不吝指出.