当前位置: > > > Swift - HTTP网络操作库SwiftHTTP使用详解1(配置,及数据请求)

Swift - HTTP网络操作库SwiftHTTP使用详解1(配置,及数据请求)

一,SwiftHTTP的说明与配置

1,什么是SwiftHTTP
SwiftHTTP本质是基于`NSURLSession`,并做了封装。使用SwiftHTTP可以让我们网络请求相关代码(如获取数据,提交数据,上传文件,下载文件等)更加简洁易用。(有点类似于我前面文章介绍的另一个网络库:Alamofire

2,SwiftHTTP的功能特性:
(1)便利的闭包API
(2)支持运行队列(NSOperationQueue)
(3)支持参数编码
(4)内置JSON请求序列化
(5)上传/下载文件带有进度
(6)代码简洁

3,SwiftHTTP的安装与配置 
(1)从 GitHub 上下载最新的代码:https://github.com/daltoniam/SwiftHTTP 
(2)将下载下来的源码包中 SwiftHTTP.xcodeproj 拖拽至你的工程中

(3)工程 -> General -> Embedded Binaries项,增加 SwiftHTTP.framework

(4)最后,在需要使用 SwiftHTTP 的地方 import 进来就可以了
import SwiftHTTP

二,使用SwiftHTTP进行数据请求
1,GET请求
(1)不带参数
do {
    let opt = try HTTP.GET("http://hangge.com")
    opt.start { response in
        //进行具体的响应操作...
    }
} catch let error {
    print("请求失败: \(error)")
}

(2)带参数
do {
    //实际的url是: http://www.hangge.com/test.php?hello=world&param2=1&ids[]=1&ids[]=2
    let opt = try HTTP.GET("http://www.hangge.com/test.php",
        parameters: ["hello": "world", "param2": 1, "ids": [1,2]])
    opt.start { response in
        //进行具体的响应操作...
    }
} catch let error {
    print("请求失败: \(error)")
}

2,POST请求
let params = ["param": "param1",
    "array": ["first array element","second","third"],
    "num": 23,
    "dict": ["someKey": "someVal"]]

do {
    let opt = try HTTP.POST("http://www.hangge.com/test.php", parameters: params)
    opt.start { response in
        //进行具体的响应操作...
    }
} catch let error {
    print("请求失败: \(error)")
}
我们使用字典作为参数,用工具可以看到发送的数据如下: 

服务端代码(test.php)如下:
<?
$param = $_POST["param"];
$num = $_POST["num"];
$dict = $_POST["dict"];
$array = $_POST["array"];

echo $param."\n";
echo $num."\n";
echo $dict["someKey"]."\n";
echo $array[0]."\n";
?>

3,响应处理
(1)获取返回的字符串数据
do {
    let opt = try HTTP.GET("http://hangge.com")
    opt.start { response in
        if let err = response.error {
            print("error: \(err.localizedDescription)")
            return
        }
        print("获取到数据: \(response.text)")
    }
} catch let error {
    print("请求失败: \(error)")
}
(2)也可先获取 NSData 数据,再转成字符串
do {
    let opt = try HTTP.GET("http://hangge.com")
    opt.start { response in
        if let err = response.error {
            print("error: \(err.localizedDescription)")
            return
        }
        let data=response.data as NSData
        let str=NSString(data: data, encoding: NSUTF8StringEncoding)
        print("获取到数据: \(str)")
    }
} catch let error {
    print("请求失败: \(error)")
}
(3)获取响应头和响应状态码
do {
    let opt = try HTTP.GET("http://hangge.com")
    opt.start { response in
        print("statusCode: \(response.statusCode)\n")
        print("headers: \(response.headers)")
    }
} catch let error {
    print("请求失败: \(error)")
}

(4)使用 response.description 可以输出所有响应信息,便于调试
do {
    let opt = try HTTP.GET("http://hangge.com")
    opt.start { response in
        print(response.description)
    }
} catch let error {
    print("请求失败: \(error)")
}

4,支持自定义Http头信息(HTTP Headers)
do {
    let opt = try HTTP.GET("http://www.hangge.com", parameters: ["hello": "there"],
        headers: ["header": "value"])
    opt.start { response in
        //进行具体的响应操作...
    }
} catch let error {
    print("请求失败: \(error)")
}

三,使用操作队列进行请求
SwiftHTTP同样支持运行队列(Operation Queue),我们可以把所有数据请求放到队列中就回自动进行多线程异步请求。
同时通过 maxConcurrentOperationCount 属性,可以设置同一时间最多允许多少个请求同时进行。
let operationQueue = NSOperationQueue()
operationQueue.maxConcurrentOperationCount = 2 //最大任务数

do {
    let opt1 = try HTTP.New("http://www.hangge.com", method: .GET)
    opt1.onFinish = { response in
        //进行具体的响应操作...
    }
    operationQueue.addOperation(opt1)
    
    let opt2 = try HTTP.New("http://www.baidu.com", method: .GET)
    opt2.onFinish = { response in
        //进行具体的响应操作...
    }
    operationQueue.addOperation(opt2)
    
    let opt3 = try HTTP.New("http://www.iteye.com", method: .GET)
    opt3.onFinish = { response in
        //进行具体的响应操作...
    }
    operationQueue.addOperation(opt3)
} catch let error {
    print("请求失败: \(error)")
}
可以使用 cancel() 方法停止单个任务:
opt2.cancel() //取消这个请求任务
也可以通过 NSOperationQueuecancelAllOperations() 方法取消所有的任务:
operationQueue.cancelAllOperations() //取消所有线程操作
评论20
  • 20楼
    2016-08-20 17:11
    小健

    非常感谢航哥,但最近又遇到问题,我用get获取网页数据时结果时nil,如http://www.qq.com,就不行,结果却又是200。

    但http://www.baidu.com又可以。 我用其他语言没出现过这种情况

    站长回复

    试了下qq.com确实获取到的是nil,我也不知道为什么会这样。你找到原因了吗?

  • 19楼
    2016-07-26 10:37
    lhw

    import SwiftHTTP这一句显示no such modules 'SwiftHTTP',但是我明明已经将下载下来的源码包中 SwiftHTTP.xcodeproj 拖拽至工程中,在Embedded Binaries项增加 SwiftHTTP.framework了

    站长回复

    如果这两步操作正确的话肯定是没问题的。你检查下Embed的时候添加的是不是iOS的framework。还有就是你clean下再build试试。

  • 18楼
    2016-07-20 00:24
    果啤

    航哥,在你这学了不少东西。发现个事,向swift项目中导入oc框架,大部分时候把一对名字相同的.m和.h文件复制添加到工程下,然后用header文件桥接一下就好了。可是导入swift的框架我感觉反而麻烦了,通常要要把整个。xcodeproj文件拖到自己的项目中,有时候不小心还会造成没有复制到自己的文件夹下。有没有好的方法能辨别出框架中的核心代码然后选中添加到自己的项目中?有时候把第三方的demo的拖进来了 觉得好别扭。不然的话只能再学cocopods了

    站长回复

    如果是一些简单的Swift第三方组件或第三方库,同样也是把swfit文件复制到项目中去。复杂的框架还是拖入xcodeproj,毕竟里面互相关联的类太多,你也不好提取,提取了以后升级库还麻烦。

    如果嫌这个麻烦,使用Cocoapods也是个很好的方案,添加升级都方便。关于Cocoapods我也有打算后面写篇相关文章。

  • 17楼
    2016-07-06 20:32
    依赖

    这个swifthttp好像只能兼容ios8以后的,要是要做成ios7.0之后的怎么弄?有没有办法?
    目前只要改为ios7.0都没法通过编译了,请站长解答

    站长回复

    SwiftHTTP要求iOS最低版本是8.0,如果是之前的版本比如7.0是没法使用的。

  • 16楼
    2016-07-06 11:11
    linjoe

    站长,如果我要给云端发送指令,该怎么发送呢
    给个思路吧,是不是在get url后面加上自己的参数?但是指令都是大括号的,我看您写的都是中括号,大括号写行不行?

    站长回复

    get请求参数的话你可以在url后面直接跟上参数:

    let opt = try HTTP.GET("http://hangge.com?uid=12323&method=add")

    也可以通过字典的形式传递参数:
    let opt = try HTTP.GET("http://www.hangge.com/test.php",
            parameters: ["hello": "world", "param2": 1, "ids": [1,2]])

    看你的意思是要传递个json串吧,你直接把它当作字符串来传递就好了。
    let jsonStr = "{\"array\": [1,2,3],\"boolean\": true}"
    let opt = try HTTP.GET("http://www.hangge.com/test.php",
                           parameters: ["jsonStr": jsonStr])

  • 15楼
    2016-07-02 18:18
    小健

    站长,我在进行具体的响应操作中去改变ui,结果需要在我改变ui的函数上加上self. ,而却并不能成功改变ui,如果不经过网络请求直接调用我ui函数则可以,请站长帮帮忙,谢谢

    站长回复

    因为数据请求不是在主线程上执行的,如果要在响应中改变页面ui,可以在调用主线程来执行。比如:

    self.textView.text = response.data
    改成:
    dispatch_async(dispatch_get_main_queue(), { () -> Void in
        self.textView.text = response.data
    })

  • 14楼
    2016-07-02 16:52
    惜缘

    为什么我使用post请求的时候不管url是什么都可以进行请求,就是说它都不会请求失败,打印data时一直打印null,求解答,非常急,万分感谢。

    站长回复

    确实是不管什么url请求都可以发送,而且都能得到response.data。但你在这之前可以先根据返回的response.error来判断是否请求成功,请求失败的话还可以通过response.error.localizedDescription来获取失败的详细原因。
    具体代码参考文章中 3(1) 样例。

  • 13楼
    2016-06-23 15:08
    半夏

    站长,问个问题,我下下来的没问题,导入项目中也是没问题的能使用,就是拖进项目的时候没有提示将文件拷贝到项目中,这样就有个问题了,我把项目的位置改变了就没有东西了,里面的库什么的 都没有了无法使用,这个应该怎么解决呢??

    站长回复

    以SwiftHTTP库为例: 

    (1)你要先将整个库文件夹拷贝到你工程目录下

    (2)再在Xcode中将 SwiftHTTP.xcodeproj 拖拽至你的工程中。
    (3)这样每次移动项目都会连同库一起移动的。

  • 12楼
    2016-05-08 17:17
    lavender

    我和2楼和3楼遇到的问题一样,无法import Swifthttp,项目中没有中文

    站长回复

    项目名里也没有swift吗?

  • 11楼
    2016-04-22 09:29
    老七

    HTTP.GET(url:String, parameters:HTTPParameterProtocol?, headers: [String : String]?, requestSerializer: HTTPSerializeProtocol)

    航大大 不好意思啊 这问题 困扰我很久 是四个参数啊 第四个参数不理解 我就是从你的连接下的 难道更新了?

    站长回复

    参见我前面一个回复。

  • 10楼
    2016-04-22 00:05
    老七

    说错了!!!是第四个参数.第三个是头我弄明白了.第四个怎么填呢?感谢

    站长回复

    第四个参数(requestSerializer)是用来将请求参数序列化的。默认是使用标准的HTTP请求序列化形式编码,如果设成JSONParameterSerializer()就是将请求参数序列化为JSON类型。

  • 9楼
    2016-04-20 12:22
    老七

    航哥 get带参数的方法,跟你的 不一样啊 一共有三个参数。第三个参数 是什么啊

    站长回复

    第三个参数用来自定义Http头信息(HTTP Headers),我文章( 二,4 )中有提到。
    一般情况下我们请求数据不需要设置http头,这个参数可以不管,不去设置它。

  • 8楼
    2016-04-20 10:28
    laoqilongxiao

    航哥:第二个方法:起那面两个参数 还知道是什么,第三个参数是什么呢?
    HTTP.GET(String)
    HTTP.GET(url:String, parameters:HTTPParameterProtocol?, headers: [String : String]?, requestSerializer: HTTPSerializeProtocol)

    站长回复

    第三个参数用来自定义Http头信息(HTTP Headers),我文章( 二,4 )中有提到。
    一般情况下我们请求数据不需要设置http头,这个参数可以不管,不去设置它。

  • 7楼
    2016-04-04 18:19
    Gavin

    航哥,我这个该怎么处理异步的问题呢,ui先于数据之前出来了,数据就展示不了了

    站长回复

    可以参考下我原来写的这篇文章:Swift - 异步加载表格数据,内容不能及时显示的问题解决(http://www.hangge.com/blog/cache/detail_1062.html)

  • 6楼
    2016-02-02 11:54
    Gemini

    航哥,请教。文中“我们使用字典作为参数,用工具可以看到发送的数据如下: ”,这里的工具是什么?

    站长回复

    抓包工具叫“charles”,你可以上网搜下,推荐使用。

  • 5楼
    2016-01-29 11:45
    13881119614

    通过get方式得到如下字符串:如何提取出 最下面的json
    获取到数据: URL:
    XXX./Login/loginProcess/robot/response.description123/username/114/password/menjiQQ

    Status Code:
    200

    Headers:
    Pragma: no-cache
    Connection: keep-alive
    X-Powered-By: PHP/5.5.9
    Content-Length: 41
    Server: nginx/1.0.15
    Content-Type: text/html
    Date: Fri, 29 Jan 2016 03:44:15 GMT
    Set-Cookie: PHPSESSID=vs1bmcbnutge93ddrsrcia4mr1; path=/
    Expires: Thu, 19 Nov 1981 08:52:00 GMT
    Cache-Control: no-store, no-cache, must-revalidate, post-check=0, pre-check=0

    Payload:
    {"result":"1","shopid":"22","bossid":"1"}

    站长回复

    response.description这个是调试用的。
    我把响应处理补上,文章已更新,你可以看下怎么取数据。

  • 4楼
    2016-01-29 11:29
    13881119614@139.com

    编译了就可以了 谢谢了 不用了 麻烦了

    站长回复

    好的

  • 3楼
    2016-01-29 10:30
    13881119614@139.com

    import SwiftHTTP这句话提示cannot load underlying module for swiftHTTP 怎么办
    没有中文啊或者带有swift

    代码如下
    import UIKit
    import SwiftHTTP

    class ViewController: UIViewController {

    override func viewDidLoad() {
    super.viewDidLoad()
    // Do any additional setup after loading the view, typically from a nib.
    }

    override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
    // Dispose of any resources that can be recreated.
    }


    }

    站长回复

    你项目名字叫什么,还有项目路径也发给我看下。这个提示其实跟swiftHTTP没什么关系

  • 2楼
    2016-01-28 21:34
    tangxinpeng

    import SwiftHTTP这句话提示cannot load underlying module for swiftHTTP 怎么办
    另外 真心非常感谢站长提高这么好的资料

    站长回复

    检查下你建的工程名字,工程名不能有不能带有‘swift’或者中文。

  • 1楼
    2016-01-28 16:05
    Gemini

    航哥,您好,看到您写的这篇关于SwiftHTTP的文章非常高兴。现在遇到一个问题。我GET需要传的parameters: 是Json类型的String,比如{"Phone":"15021208008","Type":0}。或者PUT是Json类型的Struct,比如{"Phone":"15021208008","Loc":{"Position":{"Lat":39.91295,"Lng":116.403},"Addr":"北京市东城区广场西侧路"},"ACode":"9331","Psw":"4C0FC85FA1F01624C8A4C4D938234D2D"}。不知道应该怎么写这个parameters: 请您指教,十分感谢!如能详细请教您更为感激,我的联系方式是我下面留的QQ邮箱,谢谢航哥!

    站长回复

    不管原始类型是什么,首先你要生成正确的json字符串,比如:
    let jsonString = "{\"Phone\":\"15021208008\",\"Type\":0}"
    然后get请求如下(post同理):
    let opt = try HTTP.POST("http://www.hangge.com/code/test.php", parameters: ["json":jsonString)
    服务端收到请求,取json这个参数数据即可(后面就是服务端自己解析json字符串了)