OC和Swift的AFN网络封装
2016-08-04 08:56
218 查看
一、cocopos的使用
创建项目之后,关闭项目,打开终端,cd
空格 ,把项目所在的文件夹给拖进来,
回车
pod init
然后把项目中生成的那个podfile项目拖到xcode,打开
修改 pod 'AFNetworking'
cmt+S 保存关闭
在终端输入:
pod install --no-repo-update
二、 AFN网络封装
•
在应用程序开发中,一定要封装隔离网络框架
封装AFN的Get请求.
应用程序在做网络请求的时候不会直接调用到第三方的框架,直接访问在网络工具里面创建的网络请求方法,
在网络工具类里面创建网络请求方法
报错:
status code: 200 …………. unacceptable content-type: text/html
内容格式不支持,把数据进行反序列化格式
这是一个使用AFN时最常见的错误,
OC 封装网络工具
新建网络工具类
实现单例
+(instancetype)shareTools{
static
NetTools *tools;
static
dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//注意:末尾要包含“/”
NSURL
*baseURL =[NSURL
URLWithString:@"http://www.weather.com.cn/"];
tools =[[self
alloc]initWithBaseURL:baseURL];//BaseURL,指定一个参照的地址,以后只使用参照地址就可以
//设置反序列化格式。
//因为报错:
// status code: 200 …………. unacceptable content-type: text/html
//
内容格式不支持
//直接粘过来:self.acceptableContentTypes =
[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
tools.responseSerializer.acceptableContentTypes
= [NSSet
setWithObjects:@"application/json",
@"text/json",@"text/javascript",@"text/html",nil];
});
return
tools;
}
建立网络请求方法
//创建网络请求方法
//网络请求时,把请求结果返回给调用方。使用block,异步执行完成把结果返回给调用方
-(void)request:(NSString
*)URLString parameters:(id)parameters finished:(void(^)(id
result,
NSError *error))finished{
[self
GET:URLString
parameters:parameters
success:^(NSURLSessionDataTask
*
_Nonnull task,
id
_Nullable responseObject) {
finished(responseObject,nil);
} failure:^(NSURLSessionDataTask
*
_Nullable task,
NSError *
_Nonnull error) {
NSLog(@"%@",error);
finished(nil,error);
}];
}
在调用方里面测试网络请求
[[NetTools
shareTools]
request:@"data/sk/101010100.html"
parameters:nil
finished:^(id
result,
NSError *error) {
if
(error != nil) {
NSLog(@"出错了");
return
;
}
NSLog(@"%@",result);
}];
定义一个HTTP请求类型的枚举类型
//定义一个网络请求类型的枚举
typedef
enum :NSUInteger {
GET,
POST,
}YSHRequestMethod;
//让他既支持get请求,又支持post请求,所以定义一个结构体类型
扩展这个方法的参数,加一个参数(是判断请求方法的)
-(void)request:(YSHRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters
finished:(void(^)(id result,
NSError *error))finished;
//AFN的网络请求方法,除了单词其他参数都一样的
-------------------------------------------------------------------------
[[NetTools
shareTools]request:POST
URLString:@"post"
parameters:@{@"name":
@"zhangsan",
@"age":
@18}
finished:^(id
result,
NSError *error) {
if
(error != nil) {
NSLog(@"出错了");
return
;
}
NSLog(@"%@",result);
}];
由于get和post的网络请求方法,基本一致,所以封装代码
//AFN的网络请求方法,除了单词其他参数都一样的
//判断传过来的请求方式
NSString
*methodName = (method ==
GET) ?
@"GET" :
@"POST";
//点进去看发现GET、POST等都有一个相同的方法,所以使用,但是智能提示不出来,所以。。。
//dataTaskWithHTTPMethod本类没有实现方法,但是父类实现了
//
在调用方法的时候,如果本类没有提供,直接调用父类的方法,AFN
内部已经实现这个方法!
//需要补全方法中的参数。
[[self
dataTaskWithHTTPMethod:methodName
URLString:URLString
parameters:parameters
success:^(NSURLSessionDataTask
*task,
id responseObject) {
finished(responseObject,nil);
} failure:^(NSURLSessionDataTask
*task,
NSError *error) {
NSLog(@"%@",error);
finished(nil,error);
}] resume];
从
因为那个方法是私有的方法,不能直接调用这个内部方法
在使用的地方,定义一个协议,把方法给粘过来
OC没有任何的严谨性
我们通过协议把他的一个内部的私有的方法的定义给拿出来,然后操作这个原本私有的方法。可以直接使用这个私有的方法了。
调用私有的API,但不能调用苹果的私有API,否则不能上架。
///
网络工具协议
@protocol
NetworkToolsProxy <NSObject>
///
网络请求方法
///
/// @param method HTTP
请求方法
/// @param URLString URLString
/// @param parameters
参数字典
/// @param success
成功回调
/// @param failure
失败回调
///
/// @return NSURLSessionDataTask
@optional//可以不实现,因为我们是利用继承的特点,调用了父类的方法
- (NSURLSessionDataTask
*)dataTaskWithHTTPMethod:(NSString
*)method
URLString:(NSString
*)URLString
parameters:(id)parameters
success:(void
(^)(NSURLSessionDataTask
*,
id))success
failure:(void
(^)(NSURLSessionDataTask
*,
NSError *))failure;
@end
///协议是让人遵守的,遵守协议
///
遵守网络协议 -
为了能够欺骗 Xcode
给一个智能提示,以及编译通过!
@interface
NetTools ()<NetworkToolsProxy>
@end
实现单例
// MARK:
网络工具
class
NetworkTools: AFHTTPSessionManager
{
//1.设置网络工具单例
&
响应格式设置方法
static let
sharedTools:NetworkTools
= {
let
tools = NetworkTools(baseURL:
nil)
//
设置反序列化数据格式 -
系统会自动将 OC
框架中的 NSSet
转换成 Set
tools.responseSerializer.acceptableContentTypes?.insert("text/html")
return
tools
}()
}
定义网络请求方法枚举
//定义HTTP请求方法枚举
enum
YSHRequestMethod: String
{
case
GET = "GET"
case
POSE = "POSE"
}
创建网络请求方法
// MARK: -
封装 AFN
网络方法
extension
NetworkTools {
///
网络请求
///
/// - parameter method: GET / POST
/// - parameter URLString: URLString
/// - parameter parameters:
参数字典
/// - parameter finished:
完成回调
func requedt(method:YSHRequestMethod,URLString:
String,parameters:[String:AnyObject]?,finsished:
(result:AnyObject?,error:NSError?) ->() ){
if
method == YSHRequestMethod.GET
{
//不需要用下划线替掉
GET(URLString, parameters: parameters, success: { (_, result) ->
Void
in
finsished(result: result, error:
nil )
}, failure: { (_, error) ->
Void
in
print(error)
finsished(result:
nil, error: error)
})
}
else{
POST(URLString, parameters: parameters, success: { (_,
result) -> Void
in
//
在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
finsished(result: result, error:
nil)
}, failure: { (_, error) ->
Void
in
finsished(result:
nil, error: error)
})
}
}
}
AFN 内部网络方法封装
//闭包是可以提前准备好的代码,在需要的时候调用执行,可以当做参数传递
//
定义成功回调的闭包
//想要把success传递到下面,则这个闭包的参数格式,必须和下面调用的地方的闭包的参数格式是一致的,可以直接粘贴GET调用的地方的闭包的代码。
let
success = {
(task:NSURLSessionDataTask,result:
AnyObject?) ->
Void
in
finsished(result: result, error:
nil )
}
//
定义失败回调的闭包
let failure = { (task:NSURLSessionDataTask?,error:
NSError) ->
Void
in
//
在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
print(error)
finsished(result:
nil, error: error)
}
//优化封装
if method ==
YSHRequestMethod.GET
{
GET(URLString, parameters: parameters, success: success, failure: failure)
}
else{
POST(URLString, parameters: parameters, success: success, failure: failure)
}
测试 POST 请求
NetworkTools.sharedTools.requedt(YSHRequestMethod.POSE,
URLString: "http://httpbin.org/post", parameters: ["name":
"wanglaowu"]) { (result, error) -> ()
in
print(result)
}
使用
AFN 访问方法最常见的错误
解决办法:增加 反序列化数据 格式
另外一个常见错误
创建项目之后,关闭项目,打开终端,cd
空格 ,把项目所在的文件夹给拖进来,
回车
pod init
然后把项目中生成的那个podfile项目拖到xcode,打开
修改 pod 'AFNetworking'
cmt+S 保存关闭
在终端输入:
pod install --no-repo-update
二、 AFN网络封装
•
在应用程序开发中,一定要封装隔离网络框架
封装AFN的Get请求.
应用程序在做网络请求的时候不会直接调用到第三方的框架,直接访问在网络工具里面创建的网络请求方法,
在网络工具类里面创建网络请求方法
报错:
status code: 200 …………. unacceptable content-type: text/html
内容格式不支持,把数据进行反序列化格式
这是一个使用AFN时最常见的错误,
OC 封装网络工具
新建网络工具类
NetworkTools
实现单例
+(instancetype)shareTools{
static
NetTools *tools;
static
dispatch_once_t onceToken;
dispatch_once(&onceToken, ^{
//注意:末尾要包含“/”
NSURL
*baseURL =[NSURL
URLWithString:@"http://www.weather.com.cn/"];
tools =[[self
alloc]initWithBaseURL:baseURL];//BaseURL,指定一个参照的地址,以后只使用参照地址就可以
//设置反序列化格式。
//因为报错:
// status code: 200 …………. unacceptable content-type: text/html
//
内容格式不支持
//直接粘过来:self.acceptableContentTypes =
[NSSet setWithObjects:@"application/json", @"text/json", @"text/javascript", nil];
tools.responseSerializer.acceptableContentTypes
= [NSSet
setWithObjects:@"application/json",
@"text/json",@"text/javascript",@"text/html",nil];
});
return
tools;
}
建立网络请求方法
//创建网络请求方法
//网络请求时,把请求结果返回给调用方。使用block,异步执行完成把结果返回给调用方
-(void)request:(NSString
*)URLString parameters:(id)parameters finished:(void(^)(id
result,
NSError *error))finished{
[self
GET:URLString
parameters:parameters
success:^(NSURLSessionDataTask
*
_Nonnull task,
id
_Nullable responseObject) {
finished(responseObject,nil);
} failure:^(NSURLSessionDataTask
*
_Nullable task,
NSError *
_Nonnull error) {
NSLog(@"%@",error);
finished(nil,error);
}];
}
在调用方里面测试网络请求
[[NetTools
shareTools]
request:@"data/sk/101010100.html"
parameters:nil
finished:^(id
result,
NSError *error) {
if
(error != nil) {
NSLog(@"出错了");
return
;
}
NSLog(@"%@",result);
}];
定义一个HTTP请求类型的枚举类型
//定义一个网络请求类型的枚举
typedef
enum :NSUInteger {
GET,
POST,
}YSHRequestMethod;
//让他既支持get请求,又支持post请求,所以定义一个结构体类型
扩展这个方法的参数,加一个参数(是判断请求方法的)
-(void)request:(YSHRequestMethod)method URLString:(NSString *)URLString parameters:(id)parameters
finished:(void(^)(id result,
NSError *error))finished;
//AFN的网络请求方法,除了单词其他参数都一样的
-------------------------------------------------------------------------
[[NetTools
shareTools]request:POST
URLString:@"post"
parameters:@{@"name":
@"zhangsan",
@"age":
@18}
finished:^(id
result,
NSError *error) {
if
(error != nil) {
NSLog(@"出错了");
return
;
}
NSLog(@"%@",result);
}];
由于get和post的网络请求方法,基本一致,所以封装代码
//AFN的网络请求方法,除了单词其他参数都一样的
//判断传过来的请求方式
NSString
*methodName = (method ==
GET) ?
@"GET" :
@"POST";
//点进去看发现GET、POST等都有一个相同的方法,所以使用,但是智能提示不出来,所以。。。
//dataTaskWithHTTPMethod本类没有实现方法,但是父类实现了
//
在调用方法的时候,如果本类没有提供,直接调用父类的方法,AFN
内部已经实现这个方法!
//需要补全方法中的参数。
[[self
dataTaskWithHTTPMethod:methodName
URLString:URLString
parameters:parameters
success:^(NSURLSessionDataTask
*task,
id responseObject) {
finished(responseObject,nil);
} failure:^(NSURLSessionDataTask
*task,
NSError *error) {
NSLog(@"%@",error);
finished(nil,error);
}] resume];
从
AFHTTPSessionManager.m中复制
dataTaskWithHTTPMethod函数定义
因为那个方法是私有的方法,不能直接调用这个内部方法
在使用的地方,定义一个协议,把方法给粘过来
OC没有任何的严谨性
我们通过协议把他的一个内部的私有的方法的定义给拿出来,然后操作这个原本私有的方法。可以直接使用这个私有的方法了。
调用私有的API,但不能调用苹果的私有API,否则不能上架。
///
网络工具协议
@protocol
NetworkToolsProxy <NSObject>
///
网络请求方法
///
/// @param method HTTP
请求方法
/// @param URLString URLString
/// @param parameters
参数字典
/// @param success
成功回调
/// @param failure
失败回调
///
/// @return NSURLSessionDataTask
@optional//可以不实现,因为我们是利用继承的特点,调用了父类的方法
- (NSURLSessionDataTask
*)dataTaskWithHTTPMethod:(NSString
*)method
URLString:(NSString
*)URLString
parameters:(id)parameters
success:(void
(^)(NSURLSessionDataTask
*,
id))success
failure:(void
(^)(NSURLSessionDataTask
*,
NSError *))failure;
@end
///协议是让人遵守的,遵守协议
///
遵守网络协议 -
为了能够欺骗 Xcode
给一个智能提示,以及编译通过!
@interface
NetTools ()<NetworkToolsProxy>
@end
Swift 封装网络工具
新建网络工具类NetworkTools
实现单例
// MARK:
网络工具
class
NetworkTools: AFHTTPSessionManager
{
//1.设置网络工具单例
&
响应格式设置方法
static let
sharedTools:NetworkTools
= {
let
tools = NetworkTools(baseURL:
nil)
//
设置反序列化数据格式 -
系统会自动将 OC
框架中的 NSSet
转换成 Set
tools.responseSerializer.acceptableContentTypes?.insert("text/html")
return
tools
}()
}
定义网络请求方法枚举
//定义HTTP请求方法枚举
enum
YSHRequestMethod: String
{
case
GET = "GET"
case
POSE = "POSE"
}
创建网络请求方法
// MARK: -
封装 AFN
网络方法
extension
NetworkTools {
///
网络请求
///
/// - parameter method: GET / POST
/// - parameter URLString: URLString
/// - parameter parameters:
参数字典
/// - parameter finished:
完成回调
func requedt(method:YSHRequestMethod,URLString:
String,parameters:[String:AnyObject]?,finsished:
(result:AnyObject?,error:NSError?) ->() ){
if
method == YSHRequestMethod.GET
{
//不需要用下划线替掉
GET(URLString, parameters: parameters, success: { (_, result) ->
Void
in
finsished(result: result, error:
nil )
}, failure: { (_, error) ->
Void
in
print(error)
finsished(result:
nil, error: error)
})
}
else{
POST(URLString, parameters: parameters, success: { (_,
result) -> Void
in
//
在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
finsished(result: result, error:
nil)
}, failure: { (_, error) ->
Void
in
finsished(result:
nil, error: error)
})
}
}
}
AFN 内部网络方法封装
//闭包是可以提前准备好的代码,在需要的时候调用执行,可以当做参数传递
//
定义成功回调的闭包
//想要把success传递到下面,则这个闭包的参数格式,必须和下面调用的地方的闭包的参数格式是一致的,可以直接粘贴GET调用的地方的闭包的代码。
let
success = {
(task:NSURLSessionDataTask,result:
AnyObject?) ->
Void
in
finsished(result: result, error:
nil )
}
//
定义失败回调的闭包
let failure = { (task:NSURLSessionDataTask?,error:
NSError) ->
Void
in
//
在开发网络应用的时候,错误不要提示给用户,但是错误一定要输出!
print(error)
finsished(result:
nil, error: error)
}
//优化封装
if method ==
YSHRequestMethod.GET
{
GET(URLString, parameters: parameters, success: success, failure: failure)
}
else{
POST(URLString, parameters: parameters, success: success, failure: failure)
}
测试 POST 请求
NetworkTools.sharedTools.requedt(YSHRequestMethod.POSE,
URLString: "http://httpbin.org/post", parameters: ["name":
"wanglaowu"]) { (result, error) -> ()
in
print(result)
}
小结
使用typealias可以统一和简化闭包的定义和传递
使用
baseURL能够简化网络访问方法中 URL 的传递
AFN 访问方法最常见的错误
status code == 200,但是提示
unacceptable content-type,表示网络访问正常,但是无法对返回数据做反序列化
解决办法:增加 反序列化数据 格式
另外一个常见错误
status code == 405,不支持的网络请求方法,检查 GET / POST 是否写错