你好,歡迎來到IOS教程網

 Ios教程網 >> IOS編程開發 >> IOS開發基礎 >> 自己動手寫一個 iOS 網絡請求庫(二)——封裝接口

自己動手寫一個 iOS 網絡請求庫(二)——封裝接口

編輯:IOS開發基礎

之前篇目:自己動手寫一個 iOS 網絡請求庫(一)—— NSURLSession 初探

代碼示例:https://github.com/johnlui/Swift-On-iOS/blob/master/BuildYourHTTPRequestLibrary

開源項目:Pitaya,適合大文件上傳的 HTTP 請求庫:https://github.com/johnlui/Pitaya

本篇文章中,我們將一起嘗試使用一個類來封裝我們之前的代碼,並嘗試加入動態增加 HTTP 參數(params)的功能,之後封裝出一個強大的接口。

0.jpg

基本封裝

基礎准備

新建一個 Swift 空文件,命名為 Network.swift,在裡面寫一個 Network 類,之後寫一個靜態方法 request():

class Network{
    static func request() {
        let session = NSURLSession.sharedSession()
        let request = NSURLRequest(URL: NSURL(string: "http://baidu.com")!)
        let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
            println("just wait for 5 seconds!")
            sleep(5)
            let string = NSString(data: data, encoding: NSUTF8StringEncoding)
            println(string)
        })
        task.resume()
    }
}

修改 ViewController 中的按鈕函數:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    Network.request()
}

運行項目,點擊按鈕,效果和之前一致。

自定義 HTTP method 和 URL

修改 request() 方法,將 HTTP 方法和 URL 傳進去:

static func request(method: String, url: String) {
    let session = NSURLSession.sharedSession()
    let request = NSMutableURLRequest(URL: NSURL(string: url)!)
    request.HTTPMethod = method
    let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
        println("just wait for 5 seconds!")
        sleep(5)
        let string = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string)
    })
    task.resume()
}

修改前面的函數調用:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    Network.request("GET", url: "http://baidu.com")
}

運行項目,點擊按鈕,效果和之前一致。

使用閉包處理請求結果

函數是 Swift 中的一等公民,閉包可以作為函數參數和返回值,十分強大。下面我們就用閉包來處理網絡請求的返回值。修改 request() 方法,傳遞進去一個閉包:

static func request(method: String, url: String, callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
    let session = NSURLSession.sharedSession()
    let request = NSMutableURLRequest(URL: NSURL(string: url)!)
    request.HTTPMethod = method
    let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
        callback(data: data, response: response , error: error)
    })
    task.resume()
}

在前面函數調用處使用閉包進行結果處理:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    Network.request("GET", url: "http://baidu.com") { (data, response, error) -> Void in
        println("just wait for 5 seconds!")
        sleep(5)
        let string = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string)
    }
}

運行項目,點擊按鈕,效果和之前一致。

動態增加 Params

GET 方法

GET 方法下,params 在經過 url encode 之後直接附在 URL 末尾發送給服務器。修改 request() 方法,傳遞進去一個 params 的字典:

static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
    ... ...
}

為了處理 params,我們從 Alamofire 偷來他的 params 處理函數。如果是 GET 方法,那就把處理過的 params 增加到 URL 後面。Network 類的完整代碼如下:

class Network{
    static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
        let session = NSURLSession.sharedSession()
        
        var newURL = url
        if method == "GET" {
            newURL += "?" + Network().buildParams(params)
        }
        
        let request = NSMutableURLRequest(URL: NSURL(string: newURL)!)
        request.HTTPMethod = method
        
        let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
            callback(data: data, response: response , error: error)
        })
        task.resume()
    }
    
    // 從 Alamofire 偷了三個函數
    func buildParams(parameters: [String: AnyObject]) -> String {
        var components: [(String, String)] = []
        for key in sorted(Array(parameters.keys),  [(String, String)] {
        var components: [(String, String)] = []
        if let dictionary = value as? [String: AnyObject] {
            for (nestedKey, value) in dictionary {
                components += queryComponents("\(key)[\(nestedKey)]", value)
            }
        } else if let array = value as? [AnyObject] {
            for value in array {
                components += queryComponents("\(key)", value)
            }
        } else {
            components.extend([(escape(key), escape("\(value)"))])
        }
        
        return components
    }
    func escape(string: String) -> String {
        let legalURLCharactersToBeEscaped: CFStringRef = ":&=;+!@#$()',*"
        return CFURLCreateStringByAddingPercentEscapes(nil, string, nil, legalURLCharactersToBeEscaped, CFStringBuiltInEncodings.UTF8.rawValue) as String
    }
}

修改前面的函數調用:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    Network.request("GET", url: "http://pitayaswift.sinaapp.com/pitaya.php", params: ["get": "Network"]) { (data, response, error) -> Void in
        let string = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string)
    }
}

http://pitayaswift.sinaapp.com/pitaya.php 是我部署的用於測試的服務端代碼,會直接返回 ?get=ooxx 中的 ooxx。運行項目,點擊按鈕,查看效果:


1.jpg

POST 方法

POST 方法下有幾個協議可供選擇,此處沒有文件上傳,我們采用較簡單的 application/x-www-form-urlencoded 方式發送請求。request() 方法增加一些代碼:

static func request(method: String, url: String, params: Dictionary = Dictionary(), callback: (data: NSData!, response: NSURLResponse!, error: NSError!) -> Void) {
    let session = NSURLSession.sharedSession()
    
    var newURL = url
    if method == "GET" {
        newURL += "?" + Network().buildParams(params)
    }
    
    let request = NSMutableURLRequest(URL: NSURL(string: newURL)!)
    request.HTTPMethod = method
    
    if method == "POST" {
        request.addValue("application/x-www-form-urlencoded", forHTTPHeaderField: "Content-Type")
        request.HTTPBody = Network().buildParams(params).dataUsingEncoding(NSUTF8StringEncoding)
    }
    
    let task = session.dataTaskWithRequest(request, completionHandler: { (data, response, error) -> Void in
        callback(data: data, response: response , error: error)
    })
    task.resume()
}

修改前面的函數調用:

@IBAction func mainButtonBeTapped(sender: AnyObject) {
    Network.request("POST", url: "http://pitayaswift.sinaapp.com/pitaya.php", params: ["post": "Network"]) { (data, response, error) -> Void in
        let string = NSString(data: data, encoding: NSUTF8StringEncoding)
        println(string)
    }
}

使用 POST 方式發送請求,同樣服務端會返回 key 為 post 的 value 的值。運行項目,點擊按鈕,結果和前面 GET 方法的結果一致。

至此,接口封裝完成!

下一步:自己動手寫一個 iOS 網絡請求庫(三)——降低耦合

  1. 上一頁:
  2. 下一頁:
蘋果刷機越獄教程| IOS教程問題解答| IOS技巧綜合| IOS7技巧| IOS8教程
Copyright © Ios教程網 All Rights Reserved