Just-一个轻量级网络加载库

Just.png

前言

最近在做Swift3迁移工作的时候,遇到了一个很尴尬的事情,Alamofire的库最低支持iOS 9.0了,可是我们的项目必须支持iOS 8.0+,本着不重复造轮子的想法,于是我决定换一个轻量级的网络加载库Just
原文地址

Talk is cheap, show me the code!

请求方式

Just支持的请求方式有:
DELETE
GET
HEAD
OPTIONS
PATCH
POST
PUT

同步请求\异步请求

Just支持同步请求和异步请求,Alamofre支持异步请求,不过我们平时开发中大多数请求也都是异步完成的

当我们用Swift开发时,我们倾向于避开同步网络请求,因为同步请求会阻塞主线程,这将影响Cocoa/Cocoa Touch应用程序刷新UI。然而,使用同步请求也没有什么inherantly。事实上,同步的代码通常更容易理解。

// 发起一个同步请求
var r = Just.get("http://httpbin.org/get", params:["page": 3])
// … "r" becomes available here

想变成异步请求也是非常简单的

// 发起一个异步请求
Just.get("http://httpbin.org/get", params:["page": 3]) { (r) in   
    // the same "r" is available asynchronously here
}

但是需要注意的是异步请求的callback是不运行在主线程的因此我们如果想在callback中刷新UI必须自己使用GCD或者NSOperationQueue来回到主线程

HTTP REQUEST

虽然上面的简单的例子都是调用具体的get/post请求方法 但是这些方法最终还是调用 JustAdaptor 的方法,JustAdaptor是个protocol 这就体现了Swift面向协议开发的强大之处.
Show the code:

public protocol JustAdaptor {
  func request(
    _ method: HTTPMethod, // 请求方式
    URLString: String, // 请求地址
    params: [String: Any], // 请求参数 使用字典样式
    data: [String: Any], // 请求参数 例如 表单数据
    json: Any?, // 请求参数
    headers: [String: String], // 请求头信息 字典样式
    files: [String: HTTPFile], // 上传文件
    auth: Credentials?, // 认证信息
    cookies: [String: String], // 请求cookie
    redirects: Bool, // 是否允许重定向
    timeout: Double?, // 超时时间
    URLQuery: String?, // 
    requestBody: Data?, // 请求体
    asyncProgressHandler: TaskProgressHandler?, // 进度操作 用于做上传或下载的进度
    asyncCompletionHandler: ((HTTPResult) -> Void)? // 完成操作 所有的服务器返回信息包在HTTPResult对象中
    ) -> HTTPResult

  init(session: URLSession?, defaults: JustSessionDefaults?)
}

简单的请求

GET请求
一个简单的get请求:

// 无参数
Just.get("http://httpbin.org/get"){ (r) in   
    // 异步请求结果
}
// 带参数
Just.get("http://httpbin.org/get", params:["page": 3]) { (r) in   
    // 异步请求结果
}

POST请求
一个简单的post请求:

Just.post("http://httpbin.org/post") { (r) in   
    // 异步请求结果
}

还有很多别的请求方式就不在一一赘述.

取消请求

有开启请求自然也有取消请求方法

r.cancel()

更复杂的请求

如果想发送表单数据,可以用data参数:

// 请求体会变成firstName=Barry&lastName=Allen
// Content-Type头信息将加入application/x-form-www-encoded
Just.post("http://httpbin.org/post", data:["firstName":"Barry","lastName":"Allen"])

JSON数据也是一样的

// 请求体是JSON encoded
// Content-Type头信息呢是'application/json'
Just.post("http://httpbin.org/post", json:["firstName":"Barry","lastName":"Allen"])

Redirect

默认情况下,Just会遵循服务器的redirect设置,你也可以用allowRedirect控制这种行为

// redirects
Just.get("http://httpbin.org/redirect/2").isRedirect // false
// no redirects
Just.get("http://httpbin.org/redirect/2", allowRedirects:false).isRedirect // true

此外, 你也可以设置永久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指定。 或者,一个文件可以是操作文件数据或只是一个字符串。但是在这两种情况下,需要一个文件名。

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"], // 参数
    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

如果你希望服务器返回cookie可以这么做:

// returns an NSHTTPCookie
Just.get("http://httpbin.org/cookies/set/name/elon", allowRedirects:false).cookies["name"]

发起一个带着cookie的请求

Just.get("http://httpbin.org/cookies", cookies:["test":"just"]) // ok

AUTHENTICATION

如果请求是受到基本身份验证或摘要式身份验证,请使用身份验证参数元组提供用户名和密码

Just.get("http://httpbin.org/basic-auth/flash/allen", auth:("flash", "allen")) // ok

TIMEOUT

你也可以设置超时时间

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 // 当前大小
        p.bytesExpectedToProcess // 总大小
        p.percent // 百分比
    }
) { r in
    // finished
}

CUSTOMIZATION / ADVANCED USAGE

如果你想改变Just的一些默认设置,需要使用JustSessionDefaults自定义写个性化设置

let myJustDefaults = JustSessionDefaults(
    // NSJSONSerialization reading options
    JSONReadingOptions: .mutableContainers, 
    // NSJSONSerialization writing options
    JSONWritingOptions: .prettyPrinted, 
    // 每个请求的头信息
    headers:  ["OH":"MY"],     
    // 多部分post请求边界             
    multipartBoundary: "Ju5tH77P15Aw350m3",
    // NSURLCredential持久性选项
    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请求的结果被放在一个单一的对象
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

其他描述:

// 服务器返回数据
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

总结

由于本人学识短浅,文章有错误的地方还望不吝指出.

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

推荐阅读更多精彩内容

  • Spring Cloud为开发人员提供了快速构建分布式系统中一些常见模式的工具(例如配置管理,服务发现,断路器,智...
    卡卡罗2017阅读 134,580评论 18 139
  • Android 自定义View的各种姿势1 Activity的显示之ViewRootImpl详解 Activity...
    passiontim阅读 171,387评论 25 707
  • 从三月份找实习到现在,面了一些公司,挂了不少,但最终还是拿到小米、百度、阿里、京东、新浪、CVTE、乐视家的研发岗...
    时芥蓝阅读 42,169评论 11 349
  • iOS网络编程读书笔记 Facade Tester客户端门面模式的实例(被动版本化) 被动版本化,所以硬编码URL...
    melouverrr阅读 1,598评论 3 7
  • 小猫咪GG终于被带回家了 啦啦啦,好嗨森呐 射手给大家讲讲这个救助站吧 这个救助里面有很多狗狗 很多狗狗是因为身体...
    J叔说星座阅读 387评论 0 0