iOS-----使用AFNetworking实现网络通信
使用AFNetworking实现网络通信
AFNetworking可以用于发送HTTP请求,接收HTTP响应,但不会缓存服务器响应,不能执行HTML页面中嵌入的JavaScript代码,
也不会对页面内容进行任何解析、处理,内置支持JSON、Plist属性文件、XML解析。
提交GET请求与提交POST请求
在需要使用AFNetworking的程序中使用“#import “AFHTTPRequestOperationManager.h””代码导入AFNetworking的头文件即可
使用AFNetworking发送请求、接收响应很简单,只要如下几步 |
1.创建AFHTTPRequestOperationManager对象 |
2.根据服务器响应内容的不同,为AFHTTPRequestOprationManager对象指定不同的解析器。 该对象默认的解析器要求服务器响应是JSON数据或Plist数据。 如果服务器响应数据是其他格式的,则需要手动设置响应解析器。 |
3.如果需要发送GET请求,调用AFHTTPRequestOperationManager对象的GET:parameters:success:failure:方法即可; 如果要发送POST请求,调用该对象的POST:parameters:success:failure:方法即可.两个方法都可指定通信成功、通信失败的代码块。 |
4.在success:参数指定的代码块中处理服务器响应成功的正确数据;在failure:参数指定的代码块中处理服务器响应的错误数据。 |
代码片段 |
1 /* 2 3 为了通过AFNetworking来访问被保护页面,程序同样需要使用AFNetworking来登录系统,
|
上面程序中应用程序委托的manager代表一个已经初始化完成的AFHTTPRequestOperationManager对象, 需要修改应用程序委托的application:didFinishLaunchingWithOptions:方法,保证在该方法中创建AFHTTPRequestOperationManager对象, 并指定服务器响应的解析器。 |
1 - (BOOL)application:(UIApplication*)application 2 3 didFinishLaunchingWithOptions:(NSDictionary*)launchOptions 4 5 { 6 7 // 创建AFHTTPRequestOperationManager对象 8 9 self.manager = [AFHTTPRequestOperationManager manager]; 10 11 // 为AFHTTPRequestOperationManager对象指定使用HTTP响应解析器 12 13 self.manager.responseSerializer = [[AFHTTPResponseSerializer alloc] init]; 14 15 return YES; 16 17 } 18 19 /* 20 21 创建了一个AFHTTPRequestOperationManager对象,接下来为该对象指定使用AFHTTPResponseSerializer响应解析器,
|
1 LoginController.m 2 3 @interface LoginController() 4 5 { 6 7 AppDelegate* appDelegate; 8 9 } 10 11 @end 12 13 @implementation LoginController 14 15 - (void)viewDidLoad 16 17 { 18 19 [super viewDidLoad]; 20 21 appDelegate = [UIApplication sharedApplication].delegate; 22 23 } 24 25 - (IBAction)loginBnClicked:(id)sender 26 27 { 28 29 // 获取用户输入的用户名和密码 30 31 NSString* name = self.nameFiled.text; 32 33 NSString* pass = self.passField.text; 34 35 if(name != nil && name.length > 0) 36 37 { 38 39 // 使用NSDictionary封装请求参数 40 41 NSDictionary* params = @{@”name”: name , @”pass”: pass}; 42 43 // 使用AFHTTPRequestOperationManager发送POST请求 44 45 [appDelegate.manager 46 47 POST:@http://192.168.1.88:8888/AFNetworkingServer/login.jsp 48 49 parameters:params // 指定请求参数 50 51 // 获取服务器响应成功时激发的代码块 52 53 success:^(AFHTTPRequestOperation * operation, id responseObject) 54 55 { 56 57 // 当使用HTTP响应解析器时,服务器响应数据被封装在NSData中 58 59 // 此处将NSData转换成NSString,并使用UIAlertView显示登录结果 60 61 [[[UIAlertView alloc] initWithTitle:@” 登录结果 ” message: 62 63 [[NSString alloc] initWithData:responseObject encoding: 64 65 NSUTF8StringEncoding] 66 67 delegate:self cancelButtonTitle:@”确定” otherButtonTitles:nil] 68 69 show]; 70 71 } 72 73 // 获取服务器响应失败时激发的代码块 74 75 failure:^(AFHTTPRequestOperation *operation, NSError *error) 76 77 { 78 79 NSLog(@” 获取服务器响应出错! ”); 80 81 }]; 82 } 85 } 86 87 - (IBAction)finishEdit:(id)sender 88 89 { 90 91 [sender resignFirstResponder]; 92 93 } 94 95 @end 96 97 /* 98 99 上面的红色字代码使用应用程序委托的manager属性(AFHTTPRequestOperationManager对象)的POST方法来发送POST请求,
|
处理JSON或Plist响应
AFHTTPRequestOperationManager默认就可以处理JSON或Plist响应。服务器响应数据的MIME(多用途因特网邮件扩展
(Multipurpose Internet Mail Extensions))类型是application/json、text/json(这两个代表JSON响应)、
application/x-plist(Plist响应)其中之一时,AFHTTPRequestOperationManager默认就可以处理,
无须指定服务器响应解析器。
当服务器响应数据是JSON或Plist数据,并且AFHTTPRequestOperationManager成功解析得到服务器响应时,
服务器响应数据以NSArray或NSDictionary形式返回.
/* 第1个UITableViewController对应的视图控制器类为AuthorsController,该视图控制器类将会向服务器发送GET请求, 服务器响应返回JSON格式数据.该视图控制器将把JSON响应转换为NSArray集合,并使用UITableView显示该NSArray集合数据. 下面是该视图控制器类的实现部分代码. */ |
1 AuthorsController.m 2 3 @interface AuthorsController() 4 5 { 6 7 NSArray* authors; 8 9 AppDelegate* appDelegate; 10 11 } 12 13 @end 14 15 @implementation AuthorsController 16 17 - (void)viewDidLoad 18 19 { 20 21 [super viewDidLoad]; 22 23 appDelegate = [UIApplication sharedApplication].delegate; 24 25 NSString* url = @”http://192.168.1.88:8888/AFNetworkingServer/authors.json”; 26 27 // 使用AFHTTPRequestOperationManager发送GET请求 28 29 [appDelegate.manager GET:url parameters:nil 30 31 //获取服务器响应成功时激发的代码块 32 33 success:^(AFHTTPRequestOperation* operation, id responseObject) 34 35 { 36 37 // 将服务器响应的JSON数据转换为Objective-C对象,赋值给authors属性 38 39 authors = responseObject; 40 41 // 重新加载表格数据 42 43 [self.tableView reloadData]; 44 45 } 46 47 // 获取服务器响应失败时激发的代码块 48 49 failure:^(AFHTTPRequestOperation *operation , NSError *error) 50 51 { 52 53 NSLog(@” 获取作者信息出现错误: %@ ”, error); 54 55 } 56 57 ]; 58 59 } 60 61 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 62 63 { 64 65 UITableViewCell* cell = (UITableViewCell*)sender; 66 67 // 获取激发跳转的单元格所在的NSIndexPath 68 69 NSIndexPath* indexPath = [self.tableView indexPathForCell:cell]; 70 71 // 获取即将跳转的目标视图控制器 72 73 BooksController* booksController = (BooksController*)segue.destinationViewController; 74 75 // 将用户选中的单元格的作者信息传给目标视图控制器 76 77 booksControlle.selectedAuthor = [authors objectAtIndex:indexPath.row]; // ① 78 79 } 80 81 // 省略UITableViewDataSources协议中的两个方法 82 83 ….. 84 85 @end 86 87 /* 88 89 上面的红色字代码发送GET请求时没有指定请求参数,当服务器响应是JSON数据或Plist数据时,服务器响应将被解析成NSArray或NSDictionary对象
|
服务器使用JSON格式的数据,主要基于如下两个理由 |
JSON格式是一种跨语言(几乎所有语言都支持JSON格式)的数据交换格式,而Plist的影响面就小多了。 |
Plist格式的本质依然是XML,因此Plist格式的数据在网络上的传输量更大。 |
处理XML响应
当服务器响应是XML数据时,AFNetworking必须正常处理服务器响应的XML数据,此时则需要为AFHTTPRequestOperationManager显示指定使用AFXMLParserResponseSerializer响应解析器,当使用AFXMLParserResponseSerializer解析器时,服务器返回的数据是一个NSXMLParser对象----
---可通过该对象来解析得到服务器响应的数据.
当服务器响应是XML数据时,使用AFNetworking发送请求后得到的响应是NSXMLParser对象,因此此时必须为NSXMLParser指定delegate来解析服务
器响应的XML数据.
1 @interface AuthorsController () <NSXMLParserDelegate> 2 3 { 4 5 AppDelegate* appDelegate; 6 7 NSMutableArray* authors; 8 9 NSMutableDictionary* author; 10 11 NSString* currentTagValue; 12 13 } 14 15 @end 16 17 @implementation AuthorsController 18 19 - (void)viewDidLoad 20 21 { 22 23 [super viewDidLoad]; 24 25 appDelegate = [UIApplication sharedApplication].delegate; 26 27 NSString* url = @”http://192.168.1.88:8888/AFNetworkingServer/authors.xml”; 28 29 // 使用AFHTTPRequestOperationManager发送GET请求 ① 30 31 [appDelegate.manager GET:url parameters:nil 32 33 // 获取服务器响应成功时激发的代码块 34 35 success:^(AFHTTPRequestOperation* operation, id responseObject) 36 37 { 38 39 // 获取服务器响应的XML数据,并使用NSXMLParser解析该XML数据 40 41 NSXMLParser* parser = responseObject; 42 43 // 指定解析器的delegate是该控制器本身 44 45 parser.delegate = self; 46 47 // 解析服务器响应的XML数据 48 49 [parser parse]; 50 51 // 重新加载表格数据 52 53 [self.tableView reloadData]; 54 55 } 56 57 // 获取服务器响应失败时激发的代码块 58 59 failure:^(AFHTTPRequestOperation* operation, NSError* error) 60 61 { 62 63 NSLog(@” 获取作者信息出现错误: %@” , error); 64 65 }]; 66 67 } 68 69 - (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender 70 71 { 72 73 UITableViewCell* cell = (UITableViewCell*)sender; 74 75 // 获取激发跳转的单元格所在的NSIndexPath 76 77 NSIndexPath* indexPath = [self.tableView indexPathForCell:cell]; 78 79 // 获取即将跳转到的目标视图控制器 80 81 BooksController* booksController = (BooksController*)segue.destinationViewController; 82 83 // 将用户选中的单元格的作者信息传给目标视图控制器 84 85 booksController.selecterAuthor = [authors objectAtIndexPath.row]; 86 87 } 88 89 // 省略UITableViewDataSource协议中的两个方法 90 91 …… 92 93 // 当开始处理某个元素时触发该方法 94 95 - (void)parser: (NSXMLParser*)parser didStartElement:(NSString*)elementName 96 97 namespaceURI:(NSString *)namespaceURI qualifiedName: (NSString*)qName 98 99 attributes: (NSDictionary*)attributeDict // ② 100 101 { 102 103 if([elementName isEqualToString:@”authors”]) 104 105 { 106 107 // 如果正在处理根元素,在此处初始化存储解析结果的NSMutableArray集合 108 109 authors = [[NSMutableArray alloc] init]; 110 111 } 112 113 // 如果正在处理<author…/>元素 114 115 else if([elementName isEqualToString:@”author”]) 116 117 { 118 119 // 初始化NSMutableDictionary对象 120 121 author = [[NSMutableDictionary alloc] init]; 122 123 } 124 125 } 126 127 // 当开始处理字符串内容时触发该方法 128 129 // ③ 130 131 - (void)parser:(NSXMLParser*)parser foundCharacters: (NSString*)string 132 133 { 134 135 // 如果当前的字符串值不为nil,则保存当前正在处理的元素的值 136 137 if(string) 138 139 { 140 141 currentTagValue = string; 142 143 } 144 145 } 146 147 // 当处理某个元素结束时触发该方法 148 149 - (void)parser: (NSXMLParser*)parser didEndElement: (NSString*)elementName 150 151 namespaceURI: (NSString*)namespaceURI qualifiedName: (NSString*)qName 152 153 { 154 155 // 如果处理根元素结束,则表明XML文档处理完成 156 157 if([elementName isEqualToString:@”authors”]) 158 159 { 160 161 return; 162 163 } 164 165 // 如果处理<author…/>元素结束,则将封装的NSDictionary对象添加到NSMutableArray集合中 166 167 else if([elementName isEqualToString:@”author”]) 168 169 { 170 171 [author addObject:author]; 172 173 author = nil; 174 175 } 176 177 else 178 179 { 180 181 // 如果既不是处理<authors…/>元素,也不是处理<author…/>元素 182 183 // 使用KVC方式为当前NSDictionary对象添加key-value对 184 185 [author setValue:currentTagValue forKey: elementName]; 186 187 currentTagValue = nil; 188 189 } 190 191 } 192 193 @end
|
从上面的红色字代码不难看出,当服务器响应时XML数据时,AFNetworking发送GET请求、POST请求得到的都是NSXMLParser,程序可通过该对象来解析服务器响应的XML数据------解析服务器数据时,需要自己实现NSXMLParserDelegate协议中的方法来获取服务器响应的XML数据,这样导致编程很麻烦。上面程序中的红色字代码将NSXMLParser的delegate指定为该协议中特定的方法-----------上面程序中的最后3个红色字方法就是为解析XML数据准备的. |
上传文件
使用AFNetworking上传文件直接调用AFHTTPRequestOperationManager的POST:parameters:constructingBodyWithBlock:
success:failure:方法提交POST请求即可,该方法比发送普通POST请求的方法多了第3个参数,该参数是一个带AFMultipartFormData
形参的代码块-----可以在该代码块中通过AFMultipartFormData来封装要上传的文件。
AFMultipartFormData提供了如下常用方法: |
|
- appendPartWithFileURL:name:error: |
将指定NSURL对应文件封装成上传文件 |
- appendPartWithFileURL:name:fileName:mimeType:error: |
将指定NSURL对应文件封装成上传文件.该方法可指定更多选项 |
- appendPartWithInputStream:name:fileName:length:mimeType: |
将指定输入流中的数据封装成上传文件.该方法可指定更多选项. |
- appendPartWithFileData:name:fileName:mimeType: |
将指定NSData代表的数据封装成上传文件.该方法可指定更多选项. |
代码片段 |
|
1 /* 2 3 下面程序使用一个UIPickerView来显示用户想要上传的文件,当用户选中某个文件并单击”上传”按钮后,
|
|
该程序的关键在于红色字代码块,该代码块位于AFHTTPRequestOperationManager发送POST请求的方法中,该代码块使用AFMultipartFormData的方法 把用户选中的文件封装成上传文件,随着POST请求提交给远程服务器-----远程服务器会处理用户上传的文件. |
********************************************************************************* 如需转载请注明出处---聰,地址为:http://www.cnblogs.com/congli0220/