您的位置:首页 > 理论基础 > 计算机网络

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 封装网络工具

新建网络工具类 
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 是否写错
内容来自用户分享和网络整理,不保证内容的准确性,如有侵权内容,可联系管理员处理 点击这里给我发消息
标签:  iOS开发 网络 xcode