1.AFN使用技巧
1.在開發的時候可以創建一個工具類,繼承自我們的AFN中的請求管理者,再控制器中真正發請求的代碼使用自己封裝的工具類。2.這樣做的優點是以后如果修改了底層依賴的框架,那么我們修改這個工具類就可以了,而不用再一個一個的去修改。3.該工具類一般提供一個單例方法,在該方法中會設置一個基本的請求路徑。4.該方法通常還會提供對GET或POST請求的封裝。5.在外面的時候通過該工具類來發送請求6.單例方法:+ (instancetype)shareNetworkTools{staticXMGNetworkTools *instance;staticdispatch_once_tonceToken;dispatch_once(&onceToken, ^{// 注意: BaseURL中一定要以/結尾instance = [[selfalloc] initWithBaseURL:[NSURLURLWithString:@"http://120.25.226.186:32812/"]];? ? });returninstance;}
2.AFN文件上傳
1.文件上傳拼接數據的第一種方式[formData appendPartWithFileData:data name:@"file"fileName:@"xxoo.png"mimeType:@"application/octet-stream"];2.文件上傳拼接數據的第二種方式 [formData appendPartWithFileURL:fileUrl name:@"file"fileName:@"xx.png"mimeType:@"application/octet-stream"error:nil];3.文件上傳拼接數據的第三種方式 [formData appendPartWithFileURL:fileUrl name:@"file"error:nil];4.【注】在資料中已經提供了一個用于文件上傳的分類。/*文件上傳相關的代碼如下*/-(void)upload{//1.創建一個請求管理者AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];//2.發送POST請求上傳數據/*
第一個參數:請求路徑:NSString類型
第二個參數:要上傳的非文件參數
第三個參數:block回調
在該回調中,需要利用formData拼接即將上傳的二進制數據
第三個參數:上傳成功的block回調
task:dataTask(任務)
responseObject:服務器返回的數據
第四個參數:上傳失敗的block回調
error:錯誤信息,如果上傳文件失敗,那么error里面包含了錯誤的描述信息
*/NSDictionary*dict = @{@"username":@"wenidngding"};? ? [manager POST:@"http://120.25.226.186:32812/upload"parameters:dict constructingBodyWithBlock:^(id? _Nonnull formData) {//把本地的圖片轉換為NSData類型的數據UIImage*image = [UIImageimageNamed:@"123"];NSData*data = UIImagePNGRepresentation(image);/*
//拼接二進制文件數據
第一個參數:要上傳的文件的二進制數據
第二個參數:服務器接口規定的名稱
第三個參數:這個參數上傳到服務器之后用什么名字來進行保存
第四個參數:上傳文件的MIMEType類型
*/[formData appendPartWithFileData:data name:@"file"fileName:@"xxoo.png"mimeType:@"application/octet-stream"];? ? } success:^(NSURLSessionDataTask* _Nonnull task,id_Nonnull responseObject) {NSLog(@"請求成功---%@",responseObject);? ? } failure:^(NSURLSessionDataTask* _Nonnull task,NSError* _Nonnull error) {NSLog(@"請求失敗--%@",error);? ? }];}-(void)upload2{NSLog(@"%s",__func__);//1.創建一個請求管理者AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];//2.發送POST請求上傳數據/*
第一個參數:請求路徑:NSString類型
第二個參數:要上傳的非文件參數
第三個參數:block回調
在該回調中,需要利用formData拼接即將上傳的二進制數據
第三個參數:上傳成功的block回調
task:dataTask(任務)
responseObject:服務器返回的數據
第四個參數:上傳失敗的block回調
error:錯誤信息,如果上傳文件失敗,那么error里面包含了錯誤的描述信息
*/NSDictionary*dict = @{@"username":@"wenidngding"};? ? [manager POST:@"http://120.25.226.186:32812/upload"parameters:dict constructingBodyWithBlock:^(id? _Nonnull formData) {//本地文件的urlNSURL*fileUrl = [NSURLfileURLWithPath:@"/Users/文頂頂/Desktop/KF[WTI`AQ3T`A@3R(B96D89.gif"];/*
//拼接二進制文件數據
第一個參數:要上傳文件的url路徑
第二個參數:服務器要求的參數名稱
第三個參數:這個文件上傳到服務器之后叫什么名稱
第四個參數:文件的mimetype類型
第五個參數:錯誤信息
*///? ? ? ? [formData appendPartWithFileURL:fileUrl name:@"file" fileName:@"xx.png" mimeType:@"application/octet-stream" error:nil];//另外一種上傳文件的方式/*
說明:該方法和上面的方法等價,不過該方法更加簡單其內部會自動的的根據url路徑確定文件保存名稱,并通過內部方法獲取上傳文件的mimetype類型
*/[formData appendPartWithFileURL:fileUrl name:@"file"error:nil];? ? } success:^(NSURLSessionDataTask* _Nonnull task,id_Nonnull responseObject) {NSLog(@"請求成功---%@",responseObject);? ? } failure:^(NSURLSessionDataTask* _Nonnull task,NSError* _Nonnull error) {NSLog(@"請求失敗--%@",error);? ? }];}
3.使用AFN進行序列化處理
/*
1.AFN它內部默認把服務器響應的數據當做json來進行解析,所以如果服務器返回給我的不是JSON數據那么請求報錯,這個時候需要設置AFN對響應信息的解析方式。AFN提供了三種解析響應信息的方式,分別是:
1)AFXMLParserResponseSerializer----XML
2) AFHTTPResponseSerializer---------默認二進制響應數據
3)AFJSONResponseSerializer---------JSON
2.還有一種情況就是服務器返回給我們的數據格式不太一致(開發者工具Content-Type:text/xml),那么這種情況也有可能請求不成功。解決方法:
1) 直接在源代碼中修改,添加相應的Content-Type
2) 拿到這個屬性,添加到它的集合中
3.相關代碼
-(void)srializer
{
//1.創建請求管理者,內部基于NSURLSession
AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
/* 知識點1:設置AFN采用什么樣的方式來解析服務器返回的數據*///如果返回的是XML,那么告訴AFN,響應的時候使用XML的方式解析manager.responseSerializer= [AFXMLParserResponseSerializer serializer];//如果返回的就是二進制數據,那么采用默認二進制的方式來解析數據//manager.responseSerializer = [AFHTTPResponseSerializer serializer];//采用JSON的方式來解析數據//manager.responseSerializer = [AFJSONResponseSerializer serializer];/*知識點2 告訴AFN,再序列化服務器返回的數據的時候,支持此種類型? ? [AFJSONResponseSerializer serializer].acceptableContentTypes = [NSSet setWithObject:@"text/xml"];? ? //2.把所有的請求參數通過字典的方式來裝載,GET方法內部會自動把所有的鍵值對取出以&符號拼接并最后用?符號連接在請求路徑后面? ? NSDictionary *dict = @{? ? ? ? ? ? ? ? ? ? ? ? ? @"username":@"223",? ? ? ? ? ? ? ? ? ? ? ? ? @"pwd":@"ewr",? ? ? ? ? ? ? ? ? ? ? ? ? @"type":@"XML"? ? ? ? ? ? ? ? ? ? ? ? ? };? ? //3.發送GET請求? ? [manager GET:@"http://120.25.226.186:32812/login" parameters:dict success:^(NSURLSessionDataTask * _Nonnull task, id? _Nonnull responseObject) {? ? ? ? //4.請求成功的回調block? ? ? ? NSLog(@"%@",[responseObject class]);? ? } failure:^(NSURLSessionDataTask * _Nonnull task, NSError * _Nonnull error) {? ? ? ? //5.請求失敗的回調,可以打印error的值查看錯誤信息? ? ? ? NSLog(@"%@",error);? ? }];}
4.使用AFN來檢測網絡狀態
/*
說明:可以使用AFN框架中的AFNetworkReachabilityManager來監聽網絡狀態的改變,也可以利用蘋果提供的Reachability來監聽。建議在開發中直接使用AFN框架處理。
*///使用AFN框架來檢測網絡狀態的改變-(void)AFNReachability{//1.創建網絡監聽管理者AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];//2.監聽網絡狀態的改變/*
AFNetworkReachabilityStatusUnknown? ? ? ? ? = 未知
AFNetworkReachabilityStatusNotReachable? ? = 沒有網絡
AFNetworkReachabilityStatusReachableViaWWAN = 3G
AFNetworkReachabilityStatusReachableViaWiFi = WIFI
*/[manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {switch(status) {caseAFNetworkReachabilityStatusUnknown:NSLog(@"未知");break;caseAFNetworkReachabilityStatusNotReachable:NSLog(@"沒有網絡");break;caseAFNetworkReachabilityStatusReachableViaWWAN:NSLog(@"3G");break;caseAFNetworkReachabilityStatusReachableViaWiFi:NSLog(@"WIFI");break;default:break;? ? ? ? }? ? }];//3.開始監聽[manager startMonitoring];}------------------------------------------------------------//使用蘋果提供的Reachability來檢測網絡狀態,如果要持續監聽網絡狀態的概念,需要結合通知一起使用。//提供下載地址:https://developer.apple.com/library/ios/samplecode/Reachability/Reachability.zip-(void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event{//1.注冊一個通知[[NSNotificationCenterdefaultCenter] addObserver:selfselector:@selector(networkChange) name:kReachabilityChangedNotification object:nil];//2.拿到一個對象,然后調用開始監聽方法Reachability *r = [Reachability reachabilityForInternetConnection];? ? [r startNotifier];//持有該對象,不要讓該對象釋放掉self.r= r;}//當控制器釋放的時候,移除通知的監聽-(void)dealloc{? ? [[NSNotificationCenterdefaultCenter] removeObserver:self];}-(void)networkChange{//獲取當前網絡的狀態if([Reachability reachabilityForInternetConnection].currentReachabilityStatus== ReachableViaWWAN)? ? {NSLog(@"當前網絡狀態為3G");return;? ? }if([Reachability reachabilityForLocalWiFi].currentReachabilityStatus== ReachableViaWiFi)? ? {NSLog(@"當前網絡狀態為wifi");return;? ? }NSLog(@"當前沒有網絡");}