Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
相关文章系列:(文章代码均已升级至Swift3)
[当前文章] Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)
Swift - HTTP网络操作库Alamofire使用详解4(用户权限认证)
[当前文章] Swift - HTTP网络操作库Alamofire使用详解1(配置,以及数据请求)
Swift - HTTP网络操作库Alamofire使用详解2(文件上传)
Swift - HTTP网络操作库Alamofire使用详解3(文件下载,断点续传)
Swift - HTTP网络操作库Alamofire使用详解4(用户权限认证)
一,Alamofire的说明与配置
(1)Alamofire 的前身是 AFNetworking。AFNetworking 是 iOS 和 OS X 上很受欢迎的第三方HTTP网络基础库。
(2)其实 AFNetwork 的前缀 AF 便是 Alamofire 的缩写。
(3)Swift发布后,AFNetworking的作者又用Swift语言写了个相同功能的库,这便是 Alamofire。
(4)Alamofire 本质是基于`URLSession`,并做了封装。使用 Alamofire 可以让我们网络请求相关代码(如获取数据,提交数据,上传文件,下载文件等)更加简洁易用。
(2)其实 AFNetwork 的前缀 AF 便是 Alamofire 的缩写。
(3)Swift发布后,AFNetworking的作者又用Swift语言写了个相同功能的库,这便是 Alamofire。
(4)Alamofire 本质是基于`URLSession`,并做了封装。使用 Alamofire 可以让我们网络请求相关代码(如获取数据,提交数据,上传文件,下载文件等)更加简洁易用。
关于Cookie:
Alamofire是基于URLRequest封装的,所以Cookie会自动保存,就和浏览器请求是一个效果。而且网站Set_cookie多久,本地的Cookie就多久,每次请求的时候都会自动带上cookie,直到过期。(所以像登陆session这些的都不用我们手动去处理)
Alamofire是基于URLRequest封装的,所以Cookie会自动保存,就和浏览器请求是一个效果。而且网站Set_cookie多久,本地的Cookie就多久,每次请求的时候都会自动带上cookie,直到过期。(所以像登陆session这些的都不用我们手动去处理)
2,Alamofire的功能特性:
(1)链式的请求/响应方法
(2)URL / JSON / plist参数编码
(3)上传类型支持:文件(File )、数据(Data )、流(Stream)以及MultipartFormData
(4)支持文件下载,下载支持断点续传
(5)支持使用NSURLCredential进行身份验证
(6)HTTP响应验证
(7)TLS Certificate and Public Key Pinning
(8)Progress Closure & NSProgress
3,Alamofire的安装与配置
(1)从 GitHub 上下载最新的代码:https://github.com/Alamofire/Alamofire
(2)将下载下来的源码包中 Alamofire.xcodeproj 拖拽至你的工程中
(3)工程 -> General -> Embedded Binaries项,把iOS版的framework添加进来: Alamofire.framework
(4)最后,在需要使用 Alamofire 的地方 import 进来就可以了
import Alamofire
二,使用Alamofire进行数据请求
1,以GET请求为例
(1)不带参数,不带结果处理
Alamofire.request("https://httpbin.org/get")
(2)带参数,不带结果处理
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"])
(3)带参数,也带结果处理(这里以返回结果为json格式的为例)
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) .responseJSON { response in print(response.request) // original URL request print(response.response) // URL response print(response.data) // server data print(response.result) // result of response serialization if let JSON = response.result.value { print("JSON: \(JSON)") //具体如何解析json内容可看下方“响应处理”部分 } }
2,响应处理(Response Handling)
(1)除了上面样例使用的responseJSON(处理json类型的返回结果)外,Alamofire还提供了许多其他类型的响应处理方法:
response()
responseData()
responseString(encoding: NSStringEncoding)
responseJSON(options: NSJSONReadingOptions)
responsePropertyList(options: NSPropertyListReadOptions)
responseData()
responseString(encoding: NSStringEncoding)
responseJSON(options: NSJSONReadingOptions)
responsePropertyList(options: NSPropertyListReadOptions)
(2)Response Handler
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) .response { response in print("Request: \(response.request)") print("Response: \(response.response)") print("Error: \(response.error)") if let data = response.data, let utf8Text = String(data: data, encoding: .utf8) { print("Data: \(utf8Text)") } }(3)Response Data Handler
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) .responseData { response in debugPrint("All Response Info: \(response)") if let data = response.result.value, let utf8Text = String(data: data, encoding: .utf8) { print("Data: \(utf8Text)") } }(4)Response String Handler
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) .responseString { response in print("Success: \(response.result.isSuccess)") print("Response String: \(response.result.value)") }(5)Response JSON Handler
使用responseJSON 方法的话,JSON数据会被自动转化为 Dictionary或Array。假设我们返回的json数据格式如下:
使用responseJSON自动解析json数据:
(6)同样也支持链式的返回结果处理
除了上面使用的 .Get 类型(不指定的话,默认都是使用Get请求)。Alamofire还定义了许多其他的HTTP 方法(HTTP Medthods)可以使用。
4,请求参数(Parameters)
(1)使用GET类型请求的时候,参数会自动拼接在url后面
5,参数编码方式(Parameter Encoding)
除了默认的方式外,Alamofire还支持URL、JSON、PropertyList以及自定义格式方式编码参数。
比如我们想要把一个字典类型的数据,使用json格式发起POST请求(数据将放在 body 中传输):
6,支持自定义Http头信息(HTTP Headers)
三,判断数据请求是否成功,并做相应的处理
在请求响应对象之前调用的 .validate() 函数是另一个易用的 Alamofire 特性。
将其与请求和响应链接,以确认响应的状态码在默认可接受的范围(200到299)内。如果认证失败,响应处理方法将出现一个相关错误,我们可以根据不同在完成处理方法中处理这个错误。
比如下面的样例,成功时会打印成功信息,失败时输出具体错误信息。
四,打印调试(print和debugPrint)
不管是 request对象还是 response对象都是支持打印输出的。根据不同的调试需求,我们可以自行选择使用 print 还是 debugPrint。
1,打印request对象
2,打印response对象
[
{
"name": "hangge",
"phones": [
{
"name": "公司",
"number": "123456"
},
{
"name": "家庭",
"number": "001"
}
]
},
{
"name": "big boss",
"phones": [
{
"name": "公司",
"number": "111111"
}
]
}
]
Alamofire.request("http://www.hangge.com/jsonData.php") .responseJSON { response in switch response.result.isSuccess { case true: //把得到的JSON数据转为数组 if let items = response.result.value as? NSArray{ //遍历数组得到每一个字典模型 for dict in items{ print(dict) } } case false: print(response.result.error) } }responseJSON也可以配合 SwiftyJSON 一起使用,具体可以查看我原来写的这篇文章:Swift - SwiftyJSON的使用详解
(6)同样也支持链式的返回结果处理
Alamofire.request("https://httpbin.org/get") .responseString { response in print("Response String: \(response.result.value)") } .responseJSON { response in print("Response JSON: \(response.result.value)") }3,请求类型(HTTP Methods)
除了上面使用的 .Get 类型(不指定的话,默认都是使用Get请求)。Alamofire还定义了许多其他的HTTP 方法(HTTP Medthods)可以使用。
public enum HTTPMethod: String { case options = "OPTIONS" case get = "GET" case head = "HEAD" case post = "POST" case put = "PUT" case patch = "PATCH" case delete = "DELETE" case trace = "TRACE" case connect = "CONNECT" }比如要使用 POST 请求,把 Alamofire.request 第二个参数做修改即可:
Alamofire.request("http://httpbin.org/post", method: .post)
4,请求参数(Parameters)
(1)使用GET类型请求的时候,参数会自动拼接在url后面
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) // https://httpbin.org/get?foo=bar(2)使用POST类型请求的时候,参数是放在在HTTP body里传递,url上看不到
let parameters:[String : Any] = [ "foo": "bar", "baz": ["a", 1], "qux": [ "x": 1, "y": 2, "z": 3 ] ] Alamofire.request("https://httpbin.org/post", method: .post, parameters: parameters) // HTTP body: foo=bar&baz[]=a&baz[]=1&qux[x]=1&qux[y]=2&qux[z]=3
5,参数编码方式(Parameter Encoding)
除了默认的方式外,Alamofire还支持URL、JSON、PropertyList以及自定义格式方式编码参数。
比如我们想要把一个字典类型的数据,使用json格式发起POST请求(数据将放在 body 中传输):
let parameters:[String : Any] = [ "foo": [1,2,3], "bar": [ "baz": "qux" ] ] Alamofire.request("https://httpbin.org/post", method: .post, parameters: parameters, encoding: JSONEncoding.default) // HTTP body: {"foo": [1, 2, 3], "bar": {"baz": "qux"}}服务端php页面可以这么取得发送过来的JSON数据:
<? $postdata = json_decode(file_get_contents("php://input"),TRUE); $foo= $postdata["foo"]; foreach ($foo as $item){ echo $item."|"; } //输出:1|2|3|
6,支持自定义Http头信息(HTTP Headers)
let headers: HTTPHeaders = [ "Authorization": "Basic QWxhZGRpbjpvcGVuIHNlc2FtZQ==", "Accept": "application/json" ] Alamofire.request("https://httpbin.org/headers", headers: headers) .responseJSON { response in debugPrint(response) }
三,判断数据请求是否成功,并做相应的处理
在请求响应对象之前调用的 .validate() 函数是另一个易用的 Alamofire 特性。
将其与请求和响应链接,以确认响应的状态码在默认可接受的范围(200到299)内。如果认证失败,响应处理方法将出现一个相关错误,我们可以根据不同在完成处理方法中处理这个错误。
比如下面的样例,成功时会打印成功信息,失败时输出具体错误信息。
Alamofire.request("https://httpbin.org/get", parameters: ["foo": "bar"]) .validate() .responseJSON { response in switch response.result.isSuccess { case true: print("数据获取成功!") case false: print(response.result.error) } }
四,打印调试(print和debugPrint)
不管是 request对象还是 response对象都是支持打印输出的。根据不同的调试需求,我们可以自行选择使用 print 还是 debugPrint。
1,打印request对象
let request = Alamofire.request("https://httpbin.org/ip", parameters: ["foo": "bar"]) print(request) /********** 下面是控制台输出 *************** GET https://httpbin.org/ip?foo=bar ******************************************/
let request = Alamofire.request("https://httpbin.org/ip", parameters: ["foo": "bar"]) debugPrint(request) /********** 下面是控制台输出 *************** $ curl -i \ -H "User-Agent: hangge_970/com.hangge.hangge-970 (1; OS Version 9.1 (Build 13B137))" \ -H "Accept-Encoding: gzip;q=1.0,compress;q=0.5" \ -H "Accept-Language: zh-Hans-CN;q=1.0,en-CN;q=0.9" \ "https://httpbin.org/ip?foo=bar" ******************************************/
2,打印response对象
Alamofire.request("https://httpbin.org/get") .responseString { response in debugPrint(response) } /********** 下面是控制台输出 *************** SUCCESS: { "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip;q=1.0,compress;q=0.5", "Accept-Language": "zh-Hans-CN;q=1.0,en-CN;q=0.9", "Host": "httpbin.org", "User-Agent": "hangge_970/com.hangge.hangge-970 (1; OS Version 9.1 (Build 13B137))" }, "origin": "180.109.163.139", "url": "https://httpbin.org/get" } ******************************************/
Alamofire.request(.GET, "https://httpbin.org/get") .responseString { response in print(response) } /********** 下面是控制台输出 *************** [Request]: <NSMutableURLRequest: 0x7889c780> { URL: https://httpbin.org/get } [Response]: <NSHTTPURLResponse: 0x7896f500> { URL: https://httpbin.org/get } { status code: 200, headers { "Access-Control-Allow-Origin" = "*"; "Content-Length" = 354; "Content-Type" = "application/json"; Date = "Tue, 08 Dec 2015 01:57:45 GMT"; Server = nginx; "access-control-allow-credentials" = true; } } [Data]: 354 bytes [Result]: SUCCESS: { "args": {}, "headers": { "Accept": "*/*", "Accept-Encoding": "gzip;q=1.0,compress;q=0.5", "Accept-Language": "zh-Hans-CN;q=1.0,en-CN;q=0.9", "Host": "httpbin.org", "User-Agent": "hangge_970/com.hangge.hangge-970 (1; OS Version 9.1 (Build 13B137))" }, "origin": "180.109.163.139", "url": "https://httpbin.org/get" } ******************************************/
航哥,您好,请问一下如果需要传string类型的参数 Alamofire能够实现吗? 比如我把一个字典参数序列化成一个json字符串加密之后传过去
航哥,您好,我想问下,alamofire的POST请求的请求参数里面包含空格或者中文或者特殊字符的时候请求失败,要怎么处理
航哥,您好!
Alamofire异步加载表格数据可以,但是如果需要加载到其他控件或者给某个全局变量赋值怎么办呢?
航哥,你好。
Alamofire获取数据是异步的,我在viewDidLoad中调用 网络请求一直没拿到数据,就走生成Cell了。
想问一下,这要怎么处理呢?
楼主你好 我想请问下 请求之后的数据要怎么返回的 就是 AF 的 success 和 failure 的Block
你好 我想请问下 请求成功之后 要怎么把 数据返回呢
航哥 为什么我post 传参数的时候 写个字典传过去 后台接收不到 拼接到字符串里面 就可以这种应该怎么处理啊
用alamofire已取得数据了,可是怎么没有办法绑定到TableView上呢?
// var wifi = ["StarBuck","MJ"]
var wifi = [String]()
let url = "https://httpbin.org/get"
下面Alamofire取得数据了,可是因为异步的原因,没有办法把wifi重新副值
//Alamofire取得的网络数据是异步的
Alamofire.request(url, method: .get).validate().responseJSON { (response) in
// print (response.request)
switch response.result.isSuccess {
case true:
if let value = response.result.value {
let json = JSON(value)
let headers:Dictionary<String,Any>=json["headers"].dictionaryValue
self.wifi = [String]() // 重新生成数组成功
//["Accept-Language", "Host", "Accept", "User-Agent", "Accept-Encoding"]
for (index,_) in headers{
print (index)
self.wifi.append(index)
}
}
print ("请求的headers的数据为:",self.wifi)
case false:
print ("网络请求失败")
}
}
print (wifi) //链接成功 ["Accept-Language", "Host", "Accept", "User-Agent", "Accept-Encoding"]
得到的WIFI还是空的 []
你好,我想请问下,alamofire是否支持请求参数为对象类型,例如,我有个对象User,我请求的参数为:
let parameters:[String : AnyObject] = [
"user":User(),
"other": "XXX"
]
运行提示:Invalid type in JSON write (XXXXX)
现在已经搞定了,主要是后台的大兄弟太坑爹,接收的时候没有去判断键值对这一类型所以我用了苹果原生的方法把数据传了过去。谢谢航哥,航哥你这个评论没有回复的功能,搞得要重新写个评论来回复你。。。或者给个QQ什么的进一步交流。
您好,群殴下载的 Alamofire.framework是红色的貌似显示为空的呀 是怎么回事呢
航哥,使用Alamofire我发现只能发送键值对也就是[String:AnyObject],那么我想发送一个[[String:AnyObject]],该怎么办?
文章写的灰常详细,感谢有你~
我得到这么一个值{
channels = (
{
"abbr_en" = My;
"channel_id" = 0;
name = "\U79c1\U4eba\U5146\U8d6b";
"name_en" = "Personal Radio";
"seq_id" = 0;
},
{
"abbr_en" = "";
"channel_id" = 256;
name = "SK-II \U6700\U521d\U7684\U68a6";
"name_en" = "";
"seq_id" = 0;
},
{
"abbr_en" = "";
"channel_id" = 1;
name = "\U534e\U8bed";
"name_en" = "";
"seq_id" = 1;
},
怎么去里面的值
我想在调用服务时候,如果是网络错误或者是服务器错误等非逻辑的错误,就直接使用 UIAlertController 提示出来,该怎么做呀?
Alamofire.request 我是封装到了自己写的一个公共方法里面,里面不能直接 self.presentViewController ~
站长,为什么我的参数传不过去啊?
let url = "http://apis.baidu.com/apistore/mobilenumber/mobilenumber"
let params = ["phone":"13765987654"]
let head:[String:String]=[
"apikey":"d38323ee675274026ebcfe4acfefc312"
]
Manager.sharedInstance.request(.POST, url, parameters: params, encoding: .JSON, headers: head).responseJSON { (body) -> Void in
print(body)
let data=body.data! as NSData
let jsonData = JSON(data: data)
print(jsonData)
}
{
"retData" : [
],
"retMsg" : "手机号码不能为空!",
"errNum" : -1
}
这是我返回回来的数据,我使用objectMapper封装成json过后也不行
let url = "http://apis.baidu.com/apistore/mobilenumber/mobilenumber"
let urltemp:String = url.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
Manager.sharedInstance.request(.GET, urltemp, parameters: ["phone":"15210011578"], encoding: ParameterEncoding.JSON, headers: ["apikey":"百度免费的key"]).responseJSON { (json) -> Void in
let jsonData = JSON(json.data!)
print(json)
print(jsonData)
}
为什么这个接口返回来的是一个unknown
能否解答下
站长,为什么我吧这个加入项目中编译都没法通过??
是不是xcode版本有要求?还是说有其他没有注意都的地方吗
站长,我知道我什么问题了,连接它的时候,POST只能传递字典格式,我的指令是json的,那是怎么传JSON格式呢
我的代码如下:
Alamofire.request(.GET, "http://101.200.211.1:9090/api/create",parameters: ["ssid":"用户帐号","verification":"注册的验证码"])
.validate()
.responseJSON { response in
print(response.request!)
switch response.result {
case .Success:
print(response.request)
case .Failure(let error):
print(error)
}
}
这个是传递字典格式,我想get一个JSON过去怎么弄呢?直接把JSON格式放在parameters出报错类型不符合,希望站长可以帮忙看下,谢谢咯
站长,这个如果要是请求服务器上的数据,而且不能用固定的IP,的话该怎么访问?域名吗?求一个思路
楼主,你这个是直接用的Alamofire?你有没有在使用中进行二次封装?
站长,我找你的步骤弄出现了:No such module 'Alamofire',百度的解决方法都用过了,没有用,这是怎么回事啊
环境配好 头文件引入就报错
(7)TLS Certificate and Public Key Pinning
afnManager.securityPolicy = AFSecurityPolicy(pinningMode: AFSSLPinningMode.Certificate)
afnManager.securityPolicy.allowInvalidCertificates = true
大神,求举个af中这个例子,使用Alamofire中怎么用?
hangge为什么在request请求时,主线程没有等待Alamofire,我这段代码输出时,model.info未空,错误。当把这个注释掉时,在reques请求里面可以输出这个值。这是为什么呢
Alamofire.request(.POST, urlString, parameters: parameters)
.responseJSON{ response in
let JSON = response.result.value as? NSArray
model.info = ["uid":JSON[0],"username":JSON[1],"pwd":JSON[2]]
}
//print(model.info)
航哥,我想问下 AFNetworking在发送请求的时候 会自动带上上次发送的cookie,那么alamofire好像并不会自动带上cookie,我在使用alamofire的时候,第一次发送了登陆请求之后,在后续请求中 如果不在Headers 手动带上cookie中的PHPSESSID(该网站在登陆的时候会在cookie中返回回一个名为PHPSESSID的值)的话,就无法通过该网站的验证 那我是不是可以理解为在后续的请求中并没有自动带上cookie 或者是我有什么地方疏忽、遗漏了 还请航哥指点指点 谢谢
请问下航哥得到的response能不能想以前OC那种直接赋值给NSArray 和NSDictionary 类似下面的那种。
let JSON:Array = response.result.value
请教下要是不能像上面那种赋值,得到的responsezen,要是不可以的话应该怎么写呢?航哥
时间紧迫,此问题已经折腾两天,望航哥尽快抽时间回复,感激不尽!
在使用.JSON参数编码方式发送POST请求,params参数类型是 [String: AnyObject] ,现在的需求是字典需要带一个集合,尝试很多次都没有成功,来求助于航哥,具体代码如下,key为others,value如果是个集合的话,不知道该如何组织数据,查了很多资料,都没能找到解决方案,不知是不是AnyObject不支持Array类型?望航哥受教,多谢了
let params:[String: AnyObject] = [
"name":"jack",
"age":20,
"score":98.5,
"numbers":[77,87,69,99,93],
"others":[
{"paramName":"a" , "value":1},
{"paramName":"s" , "value":2},
{"paramName":"v" , "value":4},
{"paramName":"t" , "value":5}
]
]
Alamofire.request(.POST,url,parameters: params, encoding: .JSON).responseJSON() { response in
if let json = response.result.value {
}
}
点个赞。继续学习中
文章实在太棒了,讲的非常详细,现在一百度,全部都是复制粘贴回答的问题,现在这样好的网站实在不多了
航哥真好
航兄,你好,请问为什么无论用Pod添加这个类库还是按照你本文写的都会报错?不知道你是否遇到了呢?
错误为:ld: embedded dylibs/frameworks are only supported on iOS 8.0 and later (@rpath/Alamofire.framework/Alamofire) for architecture x86_64 在stack overflow中也没找到解决方案.
如果你知道的话,请告诉我一下,谢谢!
今天的刚到公司,打开网站就看到了,赶紧打开代码进行了试验,完全ok,多谢航哥
航哥,学习了,正需要这个东西,太好了
航哥,期待更新哦!!!