###为什么要封装网络类 在开发中,会用到网络类来请求数据.我们通常会使用AFN框架,既然有了现成的框架,为什么我们还需要自己再对其进行封装呢? 如果有天,我们需要更换框架,或者某种未知原因,那么我们需要在凡是使用了AFN的地方,都要进行修改,所以,我们选择自己创建一个有关网络的类,来对AFN做进一步的封装,这样的话,即使我们需要更换AFN时,我们只需要对该网络类进行修改即可,方便维护. ###AFNetworking框架的简单介绍: AFNetworking.AFNetworking在3.0版本之后,支持的iOS最低版本为7.0,因为不支持NSURLConnectionOperation了,OS X则为10.9.
- "AFHTTPSessionManager" :网络请求管理类.整个AFN框架使用最多的一个类.内部封装的是 NSUrlSession;
- AFN 3.0版本之后,不再支持NSUrlConnection; AFN 2.0 年代使用最多的一个类 AFHTTPRequestOperationManager; 3 .AFHTTPSessionManager 和 AFHTTPRequestOperationManager 定义的方法名称完全相同.用法也完全相同.
- 一般使用了这个类,就不再使用 Reachability 框架了!(Reachability 框架:专门用来监测网络状态.)
- AFSecurityPolicy :使 AFN 支持 HTTPS 的功能.只需要一句代码就能够支持 HTTPS 请求.
- AFURLRequestSerialization :可以将请求体数据格式化成 JSON 数据.有时候,服务器需要客户端传给他一个 JSON 数据.
- AFURLResponseSerialization :AFN 默认会自动解析 JSON 数据. 如果后台传回的不是 JSON 数据,需要配置解析器类型. 解析器类型必须跟服务器返回的数据类型对应,才能够成功接收到数据!
- AFURLSessionManager : 利用这个类做文件下载!
###AFN封装 此处用的Swift进行封装.
首先我们需要用cocoa pods将AFN框架导入.
import UIKit
//引入命名空间
import AFNetworking
/**
定义一个枚举类型
- GET: 用来标识发送GET请求
- POST: 用来标识发送POST请求
*/
enum HTTPMethod {
case GET
case POST
}
/**
* 定义了一个API结构体,用来定义各种网络接口.
*/
struct API {
//此处定义了两个hostName,用来作为baseURL,一个可以用来做测试的接口,一个定义为线上接口.
static let hostName = "https://dev.xxxx.com/"
static let hostName = "https://xxxx.com/"
static let otherURL = "xxxx/xxxx" //其他的定义为用作基础URL的后面部分.
}
//该封装类继承了AFHTTPSessionManager
class SLNetworkingTool: AFHTTPSessionManager {
//创建一个单例类
static let sharedTool: SLNetworkingTool = {
let url = NSURL(string: API.hostName)
let tool = SLNetworkingTool(baseURL: url)
//根据返回来的数据,我们可以添加一些类型,用来接收网络数据.
tool.responseSerializer.acceptableContentTypes?.insert("text/html")
tool.responseSerializer.acceptableContentTypes?.insert("text/plain")
return tool
}()
/**
定义了一个对外开放的方法,用来进行网络数据的请求.
- parameter methodType: 用来决定发送的是GET还是POST请求
- parameter urlString: url接口
- parameter parameters: 发送网络请求时需要的参数,是一个字典.
- parameter finished: 完成后的回调
- parameter responseObject: 回调参数,返回请求回来的数据.
- parameter error: 如果请求成功,那么error为nil
*/
func request(methodType: HTTPMethod, urlString: String, parameters: [String : AnyObject]?, finished:(responseObject: AnyObject?, error: NSError?)->()) {
//此处定义了一个成功回调,如果回调成功,那么error为nil,
let success = { (task: NSURLSessionDataTask, responseObject: AnyObject?)->() in
finished(responseObject: responseObject, error: nil)
}
//此处定义了一个成功回调,如果回调成功,那么error不为nil,这样我们可以在使用request时,对finished里面的error参数进行判断,来确定数据是否返回成功.
let failure = { (task: NSURLSessionDataTask?, error: NSError)->() in
print(error)
finished(responseObject: nil, error: error)
}
//此处对methodType参数进行判断,来确定是发送POST还是GET请求.
if methodType == HTTPMethod.GET {
GET(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
} else {
POST(urlString, parameters: parameters, progress: nil, success: success, failure: failure)
}
}
}
上传图片的封装:
extension SLNetworkingTool {
/**
图片上传封装
- parameter urlString: 网络接口
- parameter parameters: 需要的参数
- parameter images: 上传图片的数组
- parameter finished: 完成后的回调.
*/
func sl_uploadImages(urlString : String, parameters: [String : AnyObject], images: [UIImage], finished:(responseObject: AnyObject?, error: NSError?) -> ()) {
//判断是否有图片,如果有,再进行数据的拼接.
if images.count > 0 {
//图片微博,图片上传 AFN已经封装好了AFN上传方法,使用POST方法
self.POST(urlString, parameters: parameters, constructingBodyWithBlock: { (formdata) in
//将上传的二进制数据添加到formData中
/**
1. formdata 需要上传的二进制数据
2. name 服务器接收的字段
3. fileName 服务器存储的上传文件的名称
4. mimeType 上传文件的类型 application/octet-stream 忽略文件类型,可以百度MIMEType
*/
for image in images {
let imageData = UIImagePNGRepresentation(image)!
formdata.appendPartWithFileData(imageData, name: "picture", fileName: "filename", mimeType: "application/octet-stream")
}
}, success: { (_, result) in //成功回调
finished(responseObject: result, error: nil)
}, failure: { (_, error) in //失败回调
finished(responseObject: nil, error: error)
})
}
}
}
如有错误,请多指教...