美文网首页
iOS AF的详解(一)

iOS AF的详解(一)

作者: 健健锅 | 来源:发表于2016-08-18 15:22 被阅读897次

    有没有感觉每次面试都会被问到 ,来小伙,你给我讲一下AF ,百分之八十的面试者 瞬间懵逼.再想一下如果某天 AF消失啦 ,消失啦,消失啦 怎么办,怎么办,怎么办////////////
    http://www.qingpingshan.com/rjbc/ios/105767.html
    http://www.w2bc.com/Article/13300
    http://www.cnblogs.com/polobymulberry/p/5081049.html
    http://blog.csdn.net/codywangziham01/article/details/38088017
    http://doc.okbase.net/super_man_ww/archive/228130.html
    http://blog.csdn.net/heapstackk/article/details/48680869
    http://www.cnblogs.com/chenxianming/p/5674652.html
    http://blog.sina.com.cn/s/blog_be8740510102xf4h.html
    http://blog.csdn.net/wuyouyee/article/details/51066524
    一,
    在了解AF之前 我们来先考虑一下 如果自己去搞一个网络请求怎么搞.搞定以后再去膜拜大神么写的AFNETworking.

    +(void)postByUrlPath:(NSString *)path andParams:(NSString *)params andCallBack:(CallBack)callback{
        
        NSURL *url = [NSURL URLWithString:path];
         NSMutableURLRequest *request = [NSMutableURLRequest requestWithURL:url];
        request.HTTPMethod = @"POST";
        //multipart/form-data
        //application/x-www-form-urlencoded 默认是这个 af用的也是这个格式的
         [request setValue:@"application/json;chatset=utf-8" forHTTPHeaderField:@"Content-Type"];
        NSData *data = [params dataUsingEncoding:NSUTF8StringEncoding];
        request.HTTPBody = data;
        [request setValue:[NSString stringWithFormat:@"%ld",data.length] forHTTPHeaderField:@"Content-Length"];
        NSURLSession *session = [NSURLSession sharedSession];
        NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) {
            dispatch_async(dispatch_get_main_queue(), ^{
                
                
                NSDictionary* jsonData = [NSJSONSerialization JSONObjectWithData:data options:0 error:Nil];
                NSString * str = [[NSString alloc] initWithData:data encoding:NSUTF8StringEncoding];
                NSLog(@"请求结果 ==%@    \\n$$$$ = %@",response,str);
                callback(jsonData);
    
            });
            
            
        }];
        //开始请求
        [task resume];
    }
    
    

    上面是我自己写的一个post请求
    1.首先创建 URL 并且通过URL 创建一个请求 request.
    2.接下来创建 请求方式也就是说HTTPMethod = @"POST";
    3.接下来创建 请求头[request setValue:@"application/json;chatset=utf-8" forHTTPHeaderField:@"Content-Type"];
    4.由于是post请求 需要把参数设置为请求体 并且是这长度

    [request setValue:@"application/json;chatset=utf-8" forHTTPHeaderField:@"Content-Type"];
     NSData *data = [params dataUsingEncoding:NSUTF8StringEncoding]; 
    request.HTTPBody = data; 
    [request setValue:[NSString stringWithFormat:@"%ld",data.length] forHTTPHeaderField:@"Content-Length"];
    

    目前 connect 已经废弃 所以用户session
    5.创建session 并且用session 和request 创建数据下载任务

    NSURLSession *session = [NSURLSession sharedSession]; 
    NSURLSessionDataTask *task = [session dataTaskWithRequest:request completionHandler:^(NSData *data, NSURLResponse *response, NSError *error) { dispatch_async(dispatch_get_main_queue(), ^{
    
    }
    

    其中data就是返回的数据
    二, 有木有感觉很简单 那么af是用来干嘛的 不就是网络请求么 那么他必然逃不了这个过程.
    接下来呢 我们先了解一下af的用法通过用法来一步一步去学习啊.

     AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    session.requestSerializer = [AFJSONRequestSerializer serializer];
    NSMutableDictionary *params = [NSMutableDictionary dictionary];
    params[@"start"] = @"1";
    params[@"end"] = @"5"; 
    [session POST:urlStr parameters:params progress:nil success:^(NSURLSessionDataTask * _Nonnull task, id _Nullable responseObject) { 
    NSLog(@"请求成功");
    } failure:^(NSURLSessionDataTask * _Nullable task, NSError * _Nonnull error) { 
    NSLog(@"请求成功");
    }];
    

    1.第一步创建了 一个 session管理者,并且通过管理者设置序列化为json格式的

    1. 创建请求参数字典 ,和URL
    2. 调用post方法 并且得到请求结果以block的方式返回.

    对于manager 是干啥的县不解释.
    我们在调用post方法时 才传入了URL params,由此我们可以猜到
    post方法里面 做了哪些呢 : 创建 request 并且设置请求头 请求方式,请求体. 并且通过session 创建下载任务,将返回的nsdata 返回来.
    githup 自己下载一个 af 打开我们看到


    FB42C317-D504-4AFB-8F13-597FB8131D9F.png

    查看 manager

    AFHTTPSessionManager *session = [AFHTTPSessionManager manager];
    

    我们可以在相应的文件里面常看 创建manager的过程

    5EF74465-C83C-4433-9DDD-70783E30240D.png

    可以看到 manager 最终执行的是这个步骤 并且在过程中参数都为nil 似乎看不到里面是什么有用的 ,那么紧接着 我们在看里面每个函数的意思


    7BC8568F-DAC0-4C57-BA92-0CA4F8E55027.png EADBEAF1-5274-426C-8C8F-A2EE717A6A68.png

    接下来主要理解这个方法的内容:
    NSURLSessionConfiguration 通过字面理解可以知道这是为了给session 配置(http://blog.sina.com.cn/s/blog_877e9c3c0102uzox.html) 并且开启了队列线程 设置最大为1

    接下来就是创建下载任务并且执行下面代码

    [self addDelegateForDataTask:task uploadProgress:nil downloadProgress:nil completionHandler:nil];
    

    从字面意思上看应该是添加代理给task


    A2EED5A0-E1EE-4CA4-A1D9-C85AF90CF159.png
    1665B669-E780-4320-AFFB-39FFAEC60E68.png

    通过以上代码 将 下载任务的返回属性 复制给AFURLSessionManagerTaskDelegate 看到这里后 感觉读不下去啦 因为很多不理解的地方(据说af最牛逼和巧妙的地方 就在这里 block 和代理之间的转换 ). 那么返回来接着看

    manager 创建过程已经完成.
    接下来即使调用 post 创建下载任务开始下载

    C29F5309-1DC2-4845-AC02-CEF702E6E780.png
    4156B4A6-20E9-45D3-8F7F-8F809FF34D9C.png

    在这里 创建了request 和下载任务 并且反悔了 成功和失败的详情

    接下来 看着一句的内容

    NSMutableURLRequest *request = [self.requestSerializer requestWithMethod:method URLString:[[NSURL URLWithString:URLString relativeToURL:self.baseURL] absoluteString] parameters:parameters error:&serializationError];
    
    04CFA25F-96F0-4AD9-8A96-6AFFFCA88624.png

    可以看到 这里设置啦 请求方式 接下来用这个方法给request 进行拉相应的设置


    6986F714-1117-4C49-9C0F-763DCBEF55E2.png

    在这里可以重新设置请求request


    DEA1BE7B-BDC4-4DAA-B6DB-1994317A7819.png
    接下来就是是datatask啦
     dataTask = [self dataTaskWithRequest:request
                              uploadProgress:uploadProgress
                            downloadProgress:downloadProgress
                           completionHandler:^(NSURLResponse * __unused response, id responseObject, NSError *error) 
    
    33F37966-93C6-473F-87D7-F919E27065F1.png

    第一个 红框 用request创建了 下载任务, 第二个红框 看名字addDelegate..... 以为是给datatask 添加代理,事实上 它类似与给一个model赋值,将datatask 和下载进度 以及完成结果赋值给AFURLSessionManagerTaskDelegate这个对象 接着往下看

    0048EF9B-B69B-4C02-82FE-6A186CA9EE54.png

    可以看到对delegate的各个属性进行了赋值,同事还有一个红色框的函数 setDelagate
    这个名字才是真正的给datatask 和delegate进行绑定


    64676409-B70D-40E9-8DFF-A7590A24B0C7.png

    第一个红框即使将delegate和和task的标示进行绑定 一task的标示为可以 delegate为值.
    第二个红框的函数看名字应该是添加通知或者是kvo之类的东西


    A7A83C22-AF0F-4A19-AAF5-EF363449B3E3.png
    可以看出来是注册了通知 一旦接受到task发送来的didresume名字的通知就会执行taskdidiresume 函数
    73D0F79C-B467-4879-9C07-564FD8727976.png
    可以看出来 函数里有发送了一个同名字的通知但是我知道这是什么意思

    似乎读到这了 不知道该怎么办啦 这时候我们字啊看一下 一开始我们的manager 他是


    8AE35A42-DBC7-41EF-97CB-39632EE33CB0.png

    可以看出来他是继承与AFURLSessionManager 那我们再去看AFURLSessionManager


    B79F5955-6F35-4BB8-A4F3-5872994B711A.png

    可以看出来他遵守了一系列的协议
    我们看一个NSURLSessionTaskDelegate的代理方法


    7D1F7979-2ECC-4B44-A8E2-93E3AC389388.png

    这个代理是在已经完成下载任务的代理 有任务和错误等参数,也就是说nsurlsession 下载任务完成以后会自动调用这个任务并且将task 得到.也就是常说的,iOS原生的网络结果是通过代理返回的,而 AF=通过这个model将delegate的返回值,转换成block.接着往下看,


    8C670B95-B48E-4340-8CB7-362DA55339C8.png

    通过字典的task的唯一标示获取了一开始和task绑定好的得了delegate model,然后通过delegate调用了
    [delegate URLSession:session task:task didCompleteWithError:error];
    看到这个是不是懵逼啦,这个函数不就是本身么.怎么调用 ,我在看是啥调用的是delegate调用的 别那么自然我们去delegate里面看


    538C22E0-8BA6-4EE3-8108-225AD2A7D253.png
    可以看出来他也准守了这三个代理接下来看调用的函数
    114F49C1-9500-4C43-A108-B463447C4A9E.png 6D1B4CA5-4E85-44D9-9801-71FED830D17A.png

    可以看出来在这里 分为有错误和无错误两种情况将结果以block的方式返回给了用户.当然里面还有一系列的结果序列化,这里就不看啦.
    这是个人门前对af的一个简单的阅读思路吧,接下来有时间再具体看一下

    相关文章

      网友评论

          本文标题:iOS AF的详解(一)

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