美文网首页
iOS网络编程(AFNetworking)

iOS网络编程(AFNetworking)

作者: 夜雨聲煩_ | 来源:发表于2018-05-14 15:06 被阅读0次

    作者:xx_cc
    链接:https://www.jianshu.com/p/d94cb6b58573
    來源:简书

    AFNetworking的使用

    1.GET请求
    - (void)getMethod
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        NSDictionary *dict = @{
                               @"username":@"520it",
                               @"pwd":@"520it",
                               };
        [manager GET:@"http://120.25.226.186:32812/login" parameters:dict progress:^(NSProgress * _Nonnull downloadProgress) {
            //进度
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //task 我们可以通过task拿到响应头
            //responseObject 请求成功响应结果,AF内部已经将Json转成OC对象(字典、数组)
            NSLog(@"%@",[responseObject descriptionWithLocale:nil]);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //错误信息
        }];
    }
    

    运行结果如下:

    2018-05-14 14:40:47.405543+0800 AFNetworking[18828:4930758] {
        success = "登录成功";
    }
    
    2.POST请求
    - (void)postMethod
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        NSDictionary *dict = @{
                               @"username":@"520it",
                               @"pwd":@"520it",
                               };
        [manager POST:@"http://120.25.226.186:32812/login" parameters:dict progress:^(NSProgress * _Nonnull uploadProgress) {
            //进度
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            //task 我们可以通过task拿到响应头
            //responseObject 请求成功响应结果,AF内部已经将Json转成OC对象(字典、数组)
            NSLog(@"%@",[responseObject descriptionWithLocale:nil]);
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            //错误信息
        }];
    }
    

    运行结果如下:

    2018-05-14 14:46:19.589286+0800 AFNetworking[18864:4938796] {
        success = "登录成功";
    }
    

    注意:我们发现 GET 和 POST 请求一模一样,仅仅换了一个名字,GET 请求也可以将参数放在字典中,也可以将参数拼接在 url 之后 parameters 传 nil。另外不需要开启 Task,因为 AFN 内部已经帮我们开启了
    另外:AFN 默认会把服务器返回给我们的数据当做是 JSON 数据,并且 AFN 内部已经把响应体 JSON 数据转换为 OC 对象,通常是字典或数组。

    那么如果服务器返回的XML呢?这时我们需要自己设置AFN解析方式
    manager.responseSerializer = [AFXMLParserResponseSerializer serializer];
    返回的是NSXMLParser,需要我们自己解析

    如果返回的数据既不是JSON也不是XML那么需要设置
    manager.responseSerializer = [AFHTTPResponseSerializer serializer];

    AFN默认接收的ContentTypes 有以下三种:

    • application/json
    • text/json
    • text/javascript

    如果服务器返回的ContentType不是这三种中的一种,我们就需要设置
    manager.responseSerializer.acceptableContentTypes = [NSSet setWithObject:@"text/html"];

    3.文件下载
    - (void)fileDownloadMethod
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        NSURL *url = [NSURL URLWithString:@"http://120.25.226.186:32812/resources/images/minion_03.png"];
        NSURLRequest *request = [NSURLRequest requestWithURL:url];
        NSURLSessionDownloadTask *task = [manager downloadTaskWithRequest:request progress:^(NSProgress * _Nonnull downloadProgress) {
            // downloadProgress.completedUnitCount 当前下载大小
            // downloadProgress.totalUnitCount 总大小
            NSLog(@"%f", 1.0 * downloadProgress.completedUnitCount / downloadProgress.totalUnitCount);
        } destination:^NSURL * _Nonnull(NSURL * _Nonnull targetPath, NSURLResponse * _Nonnull response) {
            // targetPath  临时存储地址
            NSLog(@"临时存储地址:%@",targetPath);
            NSString *path =[NSSearchPathForDirectoriesInDomains(NSCachesDirectory, NSUserDomainMask, YES) lastObject];
            NSString *filePath = [path stringByAppendingPathComponent:response.suggestedFilename];
            NSURL *url = [NSURL fileURLWithPath:filePath];
            NSLog(@"我们想要存储的地址:%@",filePath);
            // 返回url 我们想要存储的地址
            // response 响应头
            return url;
        } completionHandler:^(NSURLResponse * _Nonnull response, NSURL * _Nullable filePath, NSError * _Nullable error) {
            // 下载完成之后调用
            // response 响应头
            // filePath 下载存储地址
            NSLog(@"下载存储地址:%@",filePath);
        }];
        [task resume];
    }
    

    运行结果如下:

    2018-05-14 15:02:57.098191+0800 AFNetworking[19288:4970826] 1.000000
    2018-05-14 15:02:57.098544+0800 AFNetworking[19288:4970826] 临时存储地址:file:///Users/chip/Library/Developer/CoreSimulator/Devices/F8045461-CA4B-4B5A-8F14-8B5B2491948B/data/Containers/Data/Application/A67382B5-ECDF-4A3B-BE21-DFC37CC10F5F/tmp/CFNetworkDownload_D2bCws.tmp
    2018-05-14 15:02:57.101147+0800 AFNetworking[19288:4970826] 我们想要存储的地址:/Users/chip/Library/Developer/CoreSimulator/Devices/F8045461-CA4B-4B5A-8F14-8B5B2491948B/data/Containers/Data/Application/A67382B5-ECDF-4A3B-BE21-DFC37CC10F5F/Library/Caches/minion_03.png
    2018-05-14 15:02:57.102139+0800 AFNetworking[19288:4970669] 下载存储地址:file:///Users/chip/Library/Developer/CoreSimulator/Devices/F8045461-CA4B-4B5A-8F14-8B5B2491948B/data/Containers/Data/Application/A67382B5-ECDF-4A3B-BE21-DFC37CC10F5F/Library/Caches/minion_03.png
    

    注意:

    1. 下载文件需要获取NSURLSessionDownloadTask对象手动开启
    2. 第一个block块:downloadProgress 有两个属性completedUnitCount(已经下载文件大小)、totalUnitCount(文件总大小)。
    3. 第二个block块:需要返回一个url,表示想要将文件存储的地方。targetPath:表示临时存储地址在tmp临时文件中。response:响应头 可以拿到一些文件信息
    4. 第三个block块:下载完成之后调用。response:响应头。filePath:文件存储地址,与第二个block块中返回的url是一个地址
    4.文件上传

    关于文件上传使用AFN就简单多了,也不需要我们去拼接请求体和请求文件参数啦,AFN内部已经帮我们拼接好了

    方法一:formData 添加data形式数据
    - (void)uploadDataMethod1
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        [manager POST:@"http://120.25.226.186:32812/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            UIImage *image =[UIImage imageNamed:@"123"];
            if(image){
                NSData *data =UIImagePNGRepresentation(image);
                // 方法一
                /**
                 data:上传文件二进制数据
                 name:接口的名字
                 fileName:文件上传到服务器之后叫什么名字
                 mineType:上传文件的类型,可以上传任意二进制mineType.
                 */
                [formData appendPartWithFileData:data name:@"file" fileName:@"123.png" mimeType:@"image/png"];
            }else {
                NSLog(@"没有找到图片资源");
            }
            
            // 方法二
            /**
             data:上传文件二进制数据
             name:接口的名字
             这种方法内部会将文件名当做上传到服务器之后的名字,并自动获取其类型
             */
    //        [formData appendPartWithFormData:data name:@"file"];
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            // 上传进度
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            // 上传成功
            NSLog(@"上传成功");
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            // 上传失败
            NSLog(@"上传失败");
        }];
    }
    
    方法二:formData直接添加url
    - (void)uploadDataMethod2
    {
        AFHTTPSessionManager *manager = [AFHTTPSessionManager manager];
        [manager POST:@"http://120.25.226.186:32812/upload" parameters:nil constructingBodyWithBlock:^(id<AFMultipartFormData>  _Nonnull formData) {
            // formData 将要上传的数据
            // 直接传URL
            NSURL *url =[NSURL fileURLWithPath:@"/Users/yangboxing/Desktop/Snip20160905_7.png"];
            // 方法一
            [formData appendPartWithFileURL:url name:@"file" fileName:@"123.png" mimeType:@"image/png" error:nil];
            // 方法二
            /**
             这个方法会自动截取url最后一块的文件名作为上传到服务器的文件名
             也会自动获取mimeType,如果没有办法获取mimeType 就使用@"application/octet-stream" 表示任意的二进制数据 ,当我们不在意文件类型的时候 也可以用这个。
             */
            [formData appendPartWithFileURL:url name:@"file" error:nil];
        } progress:^(NSProgress * _Nonnull uploadProgress) {
            // 上传进度
        } success:^(NSURLSessionDataTask * _Nonnull task, id  _Nullable responseObject) {
            // 上传成功
            NSLog(@"上传成功");
        } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) {
            // 上传失败
            NSLog(@"上传失败");
        }];
    }
    

    注意:
    mimeType表示文件的类型,关于mimeType类型可以自行百度,我们也可以通过发送请求获取mineType

    // 通过发送请求获取mimeType
    -(NSString *)connectSync:(NSString *)path
    {
        //1.确定请求路径
        NSURL *url = [NSURL fileURLWithPath:path];
        //2.创建可变的请求对象
        NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        NSHTTPURLResponse *res = nil;
        [NSURLConnection sendSynchronousRequest:request returningResponse:&res error:nil];
        NSLog(@"%@",res.MIMEType);
        return res.MIMEType;
    }
    

    我们通过[formData appendPartWithFileURL:url name:@"file" error:nil];来看看AFN是如何获取mimeType的

    5. AFN网络状态的检测

    使用AFN进行网络状态的检测非常简单,并且可以持续监听网络状态,每当网络状态发生改变的时候,都会调用setReachabilityStatusChangeBlock方法

    AFNetworkReachabilityManager *manager = [AFNetworkReachabilityManager sharedManager];
        /*
        AFNetworkReachabilityStatusUnknown          = -1, 未知
        AFNetworkReachabilityStatusNotReachable     = 0,  没有网络
        AFNetworkReachabilityStatusReachableViaWWAN = 1,  蜂窝流量
        AFNetworkReachabilityStatusReachableViaWiFi = 2,  无线
        */
        // 监听网络状态的变化
        [manager setReachabilityStatusChangeBlock:^(AFNetworkReachabilityStatus status) {
            switch (status) {
                case AFNetworkReachabilityStatusUnknown:
                    NSLog(@"未知");
                    break;
                case AFNetworkReachabilityStatusNotReachable:
                    NSLog(@"没有网络");
                    break;
                case AFNetworkReachabilityStatusReachableViaWWAN:
                    NSLog(@"3G");
                    break;
                case AFNetworkReachabilityStatusReachableViaWiFi:
                    NSLog(@"无线");
                    break;
                    
                default:
                    break;
            }
        }];
        // 开启
        [manager startMonitoring];
    
    6. AFN向HTTPS发送请求。

    我们知道HTTPS在HTTP的基础上加入了SSL协议,SSL依靠证书来验证服务器的身份,并为浏览器和服务器之间的通信加密。
    当使用NSURLSession来向HTTPS发送请求时,需要在NSURLSessionDataDelegate的代理方法didReceiveChallenge中,信任服务器并且创建证书返回服务器。
    而AFN对此进行了很好的封装,内部已经帮我们做好这些,因此向HTTPS发送请求方法与向HTTP发送请求是一样的。

    -(void)URLSession:(NSURLSession *)session didReceiveChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
    {
        NSLog(@"--didReceiveChallenge--%@",challenge.protectionSpace);
        /*
         NSURLSessionAuthChallengeUseCredential = 0,      使用
         NSURLSessionAuthChallengePerformDefaultHandling = 1,   忽略(默认)
         NSURLSessionAuthChallengeCancelAuthenticationChallenge = 2,忽略(会取消请求)
         NSURLSessionAuthChallengeRejectProtectionSpace = 3, 忽略(下次继续询问)
         */
        // NSURLAuthenticationMethodServerTrust 服务器信任
        if ([challenge.protectionSpace.authenticationMethod isEqualToString:NSURLAuthenticationMethodServerTrust]) {
            //创建证书
            NSURLCredential *credentoal = [[NSURLCredential alloc]initWithTrust:challenge.protectionSpace.serverTrust];
            completionHandler(NSURLSessionAuthChallengeUseCredential,credentoal);
        }
    }
    

    相关文章

      网友评论

          本文标题:iOS网络编程(AFNetworking)

          本文链接:https://www.haomeiwen.com/subject/jhzddftx.html