一、cocopos的使用
创建项目之后,关闭项目,打开终端,cd 空格 ,把项目所在的文件夹给拖进来, 回车
pod init
然后把项目中生成的那个podfile 项目拖到xcode ,打开 修改 pod 'AFNetworking'
cmt+S 保存关闭
创建项目之后,关闭项目,打开终端,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 ,指定一个参照的地址,以后只使用参照地址就可以
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
// 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;
});
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);
}];
[ 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);
if (error != nil ) {
NSLog ( @" 出错了 " );
return ;
}
NSLog ( @"%@" ,result);
}];
- 定义一个HTTP请求类型的枚举类型
//
定义一个网络请求类型的枚举
typedef enum :NSUInteger {
GET,
POST,
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);
if (error != nil ) {
NSLog ( @" 出错了 " );
return ;
}
NSLog ( @"%@" ,result);
}];
- 由于get和post的网络请求方法,基本一致,所以封装代码
//AFN
的网络请求方法,除了单词其他参数都一样的
// 判断传过来的请求方式
NSString *methodName = (method == GET ) ? @"GET" : @"POST" ;
//点进去看发现GET、POST等都有一个相同的方法,所以使用,但是智能提示不出来,所以。。。
// 判断传过来的请求方式
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);
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 >
@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
}()
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"
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)
})
}
}
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)
// 定义成功回调的闭包
// 想要把 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)
print (result)
}
小结
- 使用
typealias
可以统一和简化闭包的定义和传递 - 使用
baseURL
能够简化网络访问方法中 URL 的传递 - AFN 访问方法最常见的错误
status code == 200
,但是提示unacceptable content-type
,表示网络访问正常,但是无法对返回数据做反序列化- 解决办法:增加 反序列化数据 格式
- 另外一个常见错误
status code == 405
,不支持的网络请求方法,检查 GET / POST 是否写错