美文网首页
Just-一个轻量级网络加载库

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

作者: herbsun | 来源:发表于2016-10-18 14:27 被阅读248次
    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
    

    总结

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

    相关文章

      网友评论

          本文标题:Just-一个轻量级网络加载库

          本文链接:https://www.haomeiwen.com/subject/xwwoyttx.html