iOS开发网络数据之AFNetworking使用2.0和2.5

来源:互联网 发布:720ccav新域名是什么 编辑:程序博客网 时间:2024/05/22 03:53

一 AFNetworking基本信息

1.  将AFNetworking导入项目中

注:AFNetWorking使用了ARC ,在不使用ARC项目中使用时,对AFNetWorking的所有.m文件添加“-fobjc-arc” 

2.  添加3个类库:Security.framework、MobileCoreServices.framework、SystemConfiguration.framework 

3.先编译一下程序,如果这时就有编译错误就在Prefix.pch文件中加入 

#import<SystemConfiguration/SystemConfiguration.h> 

#import<MobileCoreServices/MobileCoreServices.h> 

4.AFN的特性

(1) AFURLConnectionOperation以及他的子类都继承自NSOperation, 可以对他进行 start/cancel/pause/resume 操作,可以获取对应的 NSURLRequest 和 NSURLResponse 数据。支持 NSInputStream/NSOutputStream,提供了 uploadProgress 和 downloadProgress以方便其他使用

(2) AFNetworking可以将远程媒体数据类型(NSData)转化为可用的格式,比如JSON,XML,图像和plist。

(3)AFHTTPClient提供了一个方便的网络交互接口,包括默认头,身份验证,是否连接到网络,批量处理操作,查询字符串参数序列化,以及多种表单请求

5.AFN与系统的HTTP请求API的对应关系

l  AFURLConnectionOperation-NSOperation的子类,负责管理 NSURLConnection 并且实现其 delegate 方法。

l   AFHTTPRequestOperation - AFURLConnectionOperation 的子类,用于生成 HTTP 请求,可以区别可接受的和不可接受的状态码及内容类型

l  AFHTTPRequestOperationManager  - 包装常见 HTTP web 服务操作的类,通过AFHTTPRequestOperation 由 NSURLConnection 支持 


NSURLConnection

 

l   AFURLSessionManager  - 创建、管理基于 NSURLSessionConfiguration 对象的NSURLSession 对象的类,也可以管理 session 的数据、下载/上传任务,实现 session 和其相关联的任务的 delegate 方法。

l   AFHTTPSessionManager - AFURLSessionManager 的子类,包装常见的 HTTP web 服务操作,通过 AFURLSessionManager 由 NSURLSession 支持。 


NSURLSession (iOS 7 / Mac OS X 10.9)

 

§  AFHTTPRequestSerializer

§  AFJSONRequestSerializer

§  AFPropertyListRequestSerializer


AFURLRequestSerialization

 

§  AFJSONResponseSerializer

§  AFXMLParserResponseSerializer

§  AFXMLDocumentResponseSerializer (Mac OS X)

§  AFPropertyListResponseSerializer

§  AFImageResponseSerializer

§  AFCompoundResponseSerializer



AFURLResponseSerialization

 

  • AFSecurityPolicy
  • AFNetworkReachabilityManager

Additional Functionality



















6.AFN的简单使用

(1)AFHTTPRequestOperation

NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString: url]];  //创建一个AF的请求队列  AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc] initWithRequest:request];  //设置请求完成或失败的block  [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, id responseObject) {      NSLog(@"Success: %@", operation.responseString);      NSData *resData = [[NSData alloc]initWithData:operation.responseData];    //系统自带JSON解析      NSDictionary *resultDic = [NSJSONSerialization JSONObjectWithData:resData options:NSJSONReadingMutableLeaves error:nil];      NSLog(@"resultDic:%@",resultDic);       } failure:^(AFHTTPRequestOperation *operation, NSError *error) {      NSLog(@"Failure: %@", error);  }];  //开始执行队列中的请求  [operation start];  

(2) AFHTTPRequestOperationManager

GET和POST请求(所有的网络请求,均有manager发起 )

 要使用常规的AFN网络访问,要特别注意请求的数据的格式,否则很容易请求失败

 1. 需要注意的是,默认提交请求的数据是二进制的,返回格式是JSON  

 2. 请求格式 

     AFHTTPRequestSerializer            二进制格式 

     AFJSONRequestSerializer            JSON 

     AFPropertyListRequestSerializer    PList(是一种特殊的XML,解析起来相对容易) 

3. 返回格式 

     AFHTTPResponseSerializer           二进制格式 

     AFJSONResponseSerializer           JSON 

     AFXMLParserResponseSerializer      XML,只能返回XMLParser,还需要自己通过代理方法解析 

     AFXMLDocumentResponseSerializer (Mac OS X) 

     AFPropertyListResponseSerializer   PList 

     AFImageResponseSerializer          Image 

     AFCompoundResponseSerializer       组合 

GET请求

AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];  manager.responseSerializer = [AFHTTPResponseSerializer serializer];  //请求成功运行success块,请求失败failure块  [manager GET:@"http://www.weather.com.cn/data/sk/101010300.html" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {      NSLog(@"请求成功");  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {      NSLog(@"请求失败:%@",error);  }];
post请求
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];  NSDictionary *dict = @{@"name": @"zhangsan"};  NSDictionary *dict1 = @{@"name": @"wangwu"};  NSArray *array = @[dict, dict1];  // 设置请求格式  manager.requestSerializer = [AFJSONRequestSerializer serializer];  // 设置返回格式  manager.responseSerializer = [AFHTTPResponseSerializer serializer];  [manager POST:@"要提交数据的链接" parameters:array success:^(AFHTTPRequestOperation  operation, id responseObject) {      NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];      NSLog(@"%@", result);  } failure:^(AFHTTPRequestOperation *operation, NSError *error) {      NSLog(@"error: %@",error);  }];

(3) AFHTTPRequestSerializer & AFHTTPResponseSerializer(请求序列化和相应序列化)

//RequestSerializermanager一个post

[[AFHTTPRequestSerializer serializerrequestWithMethod:@"POST" URLString:baseUrl parameters:parameters error:nil];

AFHTTPRequestOperationManager则不需要实例化AFHTTPRequestSerializer的对象,只要设置    manager.requestSerializer = [AFHTTPRequestSerializerserializer];

7. UIKit 扩展

之前AFNetworking中的所有 UIKit category都被保留并增强,还增加了一些新的 category

     AFNetworkActivityIndicatorManager:在请求操作开始、停止加载时,自动开始、停止状态栏上的网络活动指示图标。

     UIImageView+AFNetworking:增加了 imageResponseSerializer 属性,可以轻松地让远程加载到 image view上的图像自动调整大小或应用滤镜。比如,AFCoreImageSerializer可以在 response的图像显示之前应用 Core Image filter

    UIButton+AFNetworking ():与 UIImageView+AFNetworking 类似,从远程资源加载image  backgroundImage

    UIActivityIndicatorView+AFNetworking ():根据指定的请求操作和会话任务的状态自动开始、停止 UIActivityIndicatorView

    UIProgressView+AFNetworking ():自动跟踪某个请求或会话任务的上传/下载进度。

    UIWebView+AFNetworking ():为加载 URL请求提供了更强大的API,支持进度回调和内容转换。

如何选择AFNetworking版本

首先得下载AFNetworking库文件,下载时得首先弄清楚,你将要开发的软件兼容的最低版本是多少。AFNetworking 2.0或者之后的版本需要xcode5.0版本并且只能为IOS6或更高的手机系统上运行,如果开发MAC程序,那么2.0版本只能在MAC OS X 10.8或者更高的版本上运行。

AFNetworking 2.0的下载地址https://github.com/AFNetworking/AFNetworking

如果你想要兼容IOS5或MAC OS X 10.7,那你需要用最新发布的1.x版本

AFNetworking 1.x的下载地址https://github.com/AFNetworking/AFNetworking/tree/1.x

如果要兼容4.3或者MAC OS X 10.6,需要用最新发布的0.10.x版本

AFNetworking 0.10.xhttps://github.com/AFNetworking/AFNetworking/tree/0.10.x


AFNetworking2.0

如何通过URL获取json数据

第一种,利用AFJSONRequestOperation官方网站上给的例子:

    NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];    NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    //    从URL获取json数据    AFJSONRequestOperation *operation1 = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, NSDictionary* JSON) {                NSLog(@"获取到的数据为:%@",JSON);    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id data) {        NSLog(@"发生错误!%@",error);    }];    [operation1 start];
第二种方法,利用AFHTTPRequestOperation 先获取到字符串形式的数据,然后转换成json格式,将NSString格式的数据转换成json数据,利用IOS5自带的json解析方法:

  NSString *str=[NSString stringWithFormat:@"https://alpha-api.app.net/stream/0/posts/stream/global"];    NSURL *url = [NSURL URLWithString:[str stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    NSURLRequest *request = [NSURLRequest requestWithURL:url];   AFHTTPRequestOperation *operation = [[AFHTTPRequestOperation alloc]initWithRequest:request];    [operation setCompletionBlockWithSuccess:^(AFHTTPRequestOperation *operation, idresponseObject) {        NSString *html = operation.responseString;             NSData* data=[html dataUsingEncoding:NSUTF8StringEncoding];             id dict=[NSJSONSerialization  JSONObjectWithData:data options:0 error:nil];        NSLog(@"获取到的数据为:%@",dict);    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"发生错误!%@",error);    }];    NSOperationQueue *queue = [[NSOperationQueue alloc] init];    [queue addOperation:operation];
如果发生Error Domain=NSURLErrorDomain Code=-1000 "bad URL" UserInfo=0x14defc80 {NSUnderlyingError=0x14deea10 "bad URL", NSLocalizedDescription=bad URL这个错误,请检查URL编码格式。有没有进行stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding

如何通过URL获取图片

异步获取图片,通过队列实现,而且图片会有缓存,在下次请求相同的链接时,系统会自动调用缓存,而不从网上请求数据。

UIImageView *imageView = [[UIImageView alloc] initWithFrame:CGRectMake(0.0f, 100.0f, 100.0f, 100.0f)];      [imageView setImageWithURL:[NSURL URLWithString:@"http://i.imgur.com/r4uwx.jpg"]placeholderImage:[UIImage imageNamed:@"placeholder-avatar"]];      [self.view addSubview:imageView];上面的方法是官方提供的,还有一种方法,NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"http://www.scott-sherwood.com/wp-content/uploads/2013/01/scene.png"]];    AFImageRequestOperation *operation = [AFImageRequestOperation imageRequestOperationWithRequest:request imageProcessingBlock:nil success:^(NSURLRequest *request, NSHTTPURLResponse*response, UIImage *image) {        self.backgroundImageView.image = image;    } failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error) {        NSLog(@"Error %@",error);    }];     [operation start];

如果使用第一种URLWithString  placeholderImage会有更多的细节处理,其实实现还是通过AFImageRequestOperation处理,可以点击URLWithString  placeholderImage方法进去看一下就一目了然了。所以我觉得还是用第一种好。

如何通过URL获取plist文件

通过url获取plist文件的内容,用的很少,这个方法在官方提供的方法里面没有

  NSString *weatherUrl = @"http://www.calinks.com.cn/buick/kls/Buickhousekeeper.plist";    NSURL *url = [NSURL URLWithString:[weatherUrl stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    [AFPropertyListRequestOperation addAcceptableContentTypes:[NSSet setWithObject:@"text/plain"]];    AFPropertyListRequestOperation *operation = [AFPropertyListRequestOperation propertyListRequestOperationWithRequest:request success:^(NSURLRequest *request,NSHTTPURLResponse *response, id propertyList) {        NSLog(@"%@",(NSDictionary *)propertyList);            }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, idpropertyList) {        NSLog(@"%@",error);    }];     [operation start];

如何通过URL获取XML数据

xml解析使用AFXMLRequestOperation需要实现苹果自带的NSXMLParserDelegate委托方法,XML中有一些不需要的协议格式内容,所以就不能像json那样解析,还得实现委托。我之前有想过能否所有的XML链接用一个类处理,而且跟服务端做了沟通,结果很不方便,效果不好。XML大多标签不同,格式也不固定,所以就有问题,使用json就要方便的多。

第一步;在.h文件中加入委托NSXMLParserDelegate

第二步;在.m文件方法中加入代码

NSURL *url = [NSURL URLWithString:@"http://113.106.90.22:5244/sshopinfo"];    NSURLRequest *request = [NSURLRequest requestWithURL:url];    AFXMLRequestOperation *operation =    [AFXMLRequestOperation XMLParserRequestOperationWithRequest:request success:^(NSURLRequest*request, NSHTTPURLResponse *response, NSXMLParser *XMLParser) {        XMLParser.delegate = self;        [XMLParser setShouldProcessNamespaces:YES];        [XMLParser parse];    }failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, NSXMLParser*XMLParser) {        NSLog(@"%@",error);    }];    [operation start];

第三步;在.m文件中实现委托方法

    //在文档开始的时候触发

(void)parserDidStartDocument:(NSXMLParser *)parser{    NSLog(@"解析开始!");}//解析起始标记- (void)parser:(NSXMLParser *)parser didStartElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName attributes:(NSDictionary*)attributeDict{    NSLog(@"标记:%@",elementName);    }//解析文本节点- (void)parser:(NSXMLParser *)parser foundCharacters:(NSString *)string{    NSLog(@"值:%@",string);}//解析结束标记- (void)parser:(NSXMLParser *)parser didEndElement:(NSString *)elementName namespaceURI:(NSString *)namespaceURI qualifiedName:(NSString *)qName{    NSLog(@"结束标记:%@",elementName);}//文档结束时触发-(void) parserDidEndDocument:(NSXMLParser *)parser{    NSLog(@"解析结束!");}
如何使用AFHTTPClient进行web service操作

AFHTTPClient处理GET 和 POST请求.做网页的朋友们这个方法用的比较多。在要经常调用某个请求时,可以封装,节省资源。   BaseURLString = @"http://www.raywenderlich.com/downloads/weather_sample/";    NSURL *baseURL = [NSURL URLWithString:[NSString stringWithFormat:BaseURLString]];    NSDictionary *parameters = [NSDictionary dictionaryWithObject:@"json" forKey:@"format"];    AFHTTPClient *client = [[AFHTTPClient alloc] initWithBaseURL:baseURL];        [client registerHTTPOperationClass:[AFJSONRequestOperation class]];    [client setDefaultHeader:@"Accept" value:@"text/html"];    [client postPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation*operation, id responseObject) {        NSString* newStr = [[NSString alloc] initWithData:responseObjectencoding:NSUTF8StringEncoding];        NSLog(@"POST请求:%@",newStr);    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"%@",error);    }];        [client getPath:@"weather.php" parameters:parameters success:^(AFHTTPRequestOperation*operation, id responseObject) {        NSString* newStr = [[NSString alloc] initWithData:responseObjectencoding:NSUTF8StringEncoding];        NSLog(@"GET请求:%@",newStr);    }failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"%@",error);    }];
如果需要显示网络活动指示器,可以用下面方法:

[AFNetworkActivityIndicatorManager sharedManager].enabled = YES;

AFNetworking2.5

1.检测网络状态

+ (void)netWorkStatus{    /**     AFNetworkReachabilityStatusUnknown          = -1,  // 未知     AFNetworkReachabilityStatusNotReachable     = 0,   // 无连接     AFNetworkReachabilityStatusReachableViaWWAN = 1,   // 3G 花钱     AFNetworkReachabilityStatusReachableViaWiFi = 2,   // WiFi     */    // 如果要检测网络状态的变化,必须用检测管理器的单例的startMonitoring    [[AFNetworkReachabilityManager sharedManager] startMonitoring];        // 检测网络连接的单例,网络变化时的回调方法    [[AFNetworkReachabilityManager sharedManager] setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {        NSLog(@"%ld", status);    }];}
2.JSON方式获取数据

+ (void)JSONDataWithUrl:(NSString *)url success:(void (^)(id json))success fail:(void (^)())fail;{    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];        NSDictionary *dict = @{@"format": @"json"};    // 网络访问是异步的,回调是主线程的,因此程序员不用管在主线程更新UI的事情    [manager GET:url parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {        if (success) {            success(responseObject);        }    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"%@", error);        if (fail) {            fail();        }    }];}
3.xml方式获取数据
+ (void)XMLDataWithUrl:(NSString *)urlStr success:(void (^)(id xml))success fail:(void (^)())fail{    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];        // 返回的数据格式是XML    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];        NSDictionary *dict = @{@"format": @"xml"};        // 网络访问是异步的,回调是主线程的,因此程序员不用管在主线程更新UI的事情    [manager GET:urlStr parameters:dict success:^(AFHTTPRequestOperation *operation, id responseObject) {        if (success) {            success(responseObject);        }            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"%@", error);        if (fail) {            fail();        }    }];}
4.post提交json数据
+ (void)postJSONWithUrl:(NSString *)urlStr parameters:(id)parameters success:(void (^)(id responseObject))success fail:(void (^)())fail{    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];    // 设置请求格式    manager.requestSerializer = [AFJSONRequestSerializer serializer];    // 设置返回格式    manager.responseSerializer = [AFHTTPResponseSerializer serializer];    [manager POST:urlStr parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {//        NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];        if (success) {            success(responseObject);        }    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"%@", error);        if (fail) {            fail();        }    }];    }
5.下载文件
+ (void)sessionDownloadWithUrl:(NSString *)urlStr success:(void (^)(NSURL *fileURL))success fail:(void (^)())fail{    NSURLSessionConfiguration *config = [NSURLSessionConfiguration defaultSessionConfiguration];    AFURLSessionManager *manager = [[AFURLSessionManager alloc] initWithSessionConfiguration:config];    NSString *urlString = [urlStr stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];        NSURL *url = [NSURL URLWithString:urlString];    NSURLRequest *request = [NSURLRequest requestWithURL:url];        NSURLSessionDownloadTask *task = [manager downloadTaskWithRequest:request progress:nil destination:^NSURL *(NSURL *targetPath, NSURLResponse *response) {        // 指定下载文件保存的路径        //        NSLog(@"%@ %@", targetPath, response.suggestedFilename);        // 将下载文件保存在缓存路径中        NSString *cacheDir = NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES)[0];        NSString *path = [cacheDir stringByAppendingPathComponent:response.suggestedFilename];                // URLWithString返回的是网络的URL,如果使用本地URL,需要注意//        NSURL *fileURL1 = [NSURL URLWithString:path];        NSURL *fileURL = [NSURL fileURLWithPath:path];        //        NSLog(@"== %@ |||| %@", fileURL1, fileURL);        if (success) {            success(fileURL);        }                return fileURL;    } completionHandler:^(NSURLResponse *response, NSURL *filePath, NSError *error) {        NSLog(@"%@ %@", filePath, error);        if (fail) {            fail();        }    }];        [task resume];}
6.文件上传-自定义上传文件名
+ (void)postUploadWithUrl:(NSString *)urlStr fileUrl:(NSURL *)fileURL fileName:(NSString *)fileName fileType:(NSString *)fileTye success:(void (^)(id responseObject))success fail:(void (^)())fail{    // 本地上传给服务器时,没有确定的URL,不好用MD5的方式处理    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];    manager.responseSerializer = [AFHTTPResponseSerializer serializer];    //@"http://localhost/demo/upload.php"    [manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {        //        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"头像1.png" withExtension:nil];                // 要上传保存在服务器中的名称        // 使用时间来作为文件名 2014-04-30 14:20:57.png        // 让不同的用户信息,保存在不同目录中//        NSDateFormatter *formatter = [[NSDateFormatter alloc] init];//        // 设置日期格式//        formatter.dateFormat = @"yyyy-MM-dd HH:mm:ss";//        NSString *fileName = [formatter stringFromDate:[NSDate date]];                //@"image/png"        [formData appendPartWithFileURL:fileURL name:@"uploadFile" fileName:fileName mimeType:fileTye error:NULL];            } success:^(AFHTTPRequestOperation *operation, id responseObject) {        if (success) {            success(responseObject);        }    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        if (fail) {            fail();        }    }];}
7.文件上传-随机生成文件名
+ (void)postUploadWithUrl:(NSString *)urlStr fileUrl:(NSURL *)fileURL success:(void (^)(id responseObject))success fail:(void (^)())fail{    AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];    // AFHTTPResponseSerializer就是正常的HTTP请求响应结果:NSData    // 当请求的返回数据不是JSON,XML,PList,UIImage之外,使用AFHTTPResponseSerializer    // 例如返回一个html,text...    //    // 实际上就是AFN没有对响应数据做任何处理的情况    manager.responseSerializer = [AFHTTPResponseSerializer serializer];        // formData是遵守了AFMultipartFormData的对象    [manager POST:urlStr parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData> formData) {                // 将本地的文件上传至服务器//        NSURL *fileURL = [[NSBundle mainBundle] URLForResource:@"头像1.png" withExtension:nil];                [formData appendPartWithFileURL:fileURL name:@"uploadFile" error:NULL];    } success:^(AFHTTPRequestOperation *operation, id responseObject) {//        NSString *result = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];//        //        NSLog(@"完成 %@", result);        if (success) {            success(responseObject);        }    } failure:^(AFHTTPRequestOperation *operation, NSError *error) {        NSLog(@"错误 %@", error.localizedDescription);        if (fail) {            fail();        }    }];}

0 0