开源中国iOS客户端学习——(八)网络通信AFNetworking类库

本文介绍了AFNetworking库在iOS客户端中的使用方法,重点讲解了getPath和postPath两个实例方法的功能与实现细节,并通过实际代码示例展示了如何进行GET和POST请求。

摘要生成于 C知道 ,由 DeepSeek-R1 满血版支持, 前往体验 >

---------------------------------------------------------------------------------------------------------------------------

2015.8.19 更新

考虑到还会有很多童鞋会看到该Blog,在此做一个说明,开源中国iOS开源客户端源码已做重构,请下载最新的源码学习(注:本Blog不一定适用与新的代码学习)。

新repo地址:http://git.oschina.net/oschina/iphone-app

另外,这篇Blog收集了一些其他社区的客户端源码,源码也正在不断更新中,有的也上架appstore。

访问地址:http://duxinfeng.com/2015/07/14/iOS%E5%BC%80%E6%BA%90App%E6%95%B4%E7%90%86/

---------------------------------------------------------------------------------------------------------------------------

AFNetworking是一个轻量级的iOS网络通信类库,继ASI类库不在更新之后开发者们有一套不错选择;

AFNetworking类库源码下载和使用教程: https://github.com/AFNetworking/AFNetworking

如果想深入研究有官方文档介绍:http://afnetworking.github.com/AFNetworking/


在开源中国iOS客户端中关于AFNetworking类库的使用只用到了两个实例方法

(1)getPath:parameters:success:failure:

(2)postPath:parameters:success:failure:

他们用法基本相同,只是请求数据方式不同,一种是Get请求和Post请求Get是向服务器发索取数据的一种请求,也就相当于查询信息功能,不会修改类容,Post是向服务器提交数据的一种请求,影响数据内容;两种方法定义:


- (void)getPath:(NSString *)path 
     parameters:(NSDictionary *)parameters 
        success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
        failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
	NSURLRequest *request = [self requestWithMethod:@"GET" path:path parameters:parameters];
    AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self enqueueHTTPRequestOperation:operation];
}

- (void)postPath:(NSString *)path 
      parameters:(NSDictionary *)parameters 
         success:(void (^)(AFHTTPRequestOperation *operation, id responseObject))success
         failure:(void (^)(AFHTTPRequestOperation *operation, NSError *error))failure
{
	NSURLRequest *request = [self requestWithMethod:@"POST" path:path parameters:parameters];
	AFHTTPRequestOperation *operation = [self HTTPRequestOperationWithRequest:request success:success failure:failure];
    [self enqueueHTTPRequestOperation:operation];
}



getPath:parameters:success:failure:方法在程序中使用举例:

NewsView.m

- (void)reload:(BOOL)noRefresh
{
    //如果有网络连接
    if ([Config Instance].isNetworkRunning) {
        if (isLoading || isLoadOver) {
            return;
        }
        if (!noRefresh) {
            allCount = 0;
        }
        int pageIndex = allCount/20;
        NSString *url;

        switch (self.catalog) {
            case 1:
                url = [NSString stringWithFormat:@"%@?catalog=%d&pageIndex=%d&pageSize=%d", api_news_list, 1, pageIndex, 20];
                break;
            case 2:
                url = [NSString stringWithFormat:@"%@?type=latest&pageIndex=%d&pageSize=%d", api_blog_list, pageIndex, 20];
                break;
            case 3:
                url = [NSString stringWithFormat:@"%@?type=recommend&pageIndex=%d&pageSize=%d", api_blog_list, pageIndex, 20];
                break;
        }

        [[AFOSCClient sharedClient]getPath:url parameters:Nil 
            
          success:^(AFHTTPRequestOperation *operation, id responseObject) {
               
            [Tool getOSCNotice2:operation.responseString];
            isLoading = NO;
            if (!noRefresh) {
                [self clear];
            }

            @try {
                NSMutableArray *newNews = self.catalog <= 1 ?
                
                [Tool readStrNewsArray:operation.responseString andOld: news]:
                [Tool readStrUserBlogsArray:operation.responseString andOld: news];
                int count = [Tool isListOver2:operation.responseString];
                allCount += count;
                if (count < 20)
                {
                    isLoadOver = YES;
                }
                [news addObjectsFromArray:newNews];
                [self.tableNews reloadData];
                [self doneLoadingTableViewData];
                
                //如果是第一页 则缓存下来
                if (news.count <= 20) {
                    [Tool saveCache:5 andID:self.catalog andString:operation.responseString];
                }
            }
            @catch (NSException *exception) {
                [NdUncaughtExceptionHandler TakeException:exception];
            }
            @finally {
                [self doneLoadingTableViewData];
            }
        } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
            NSLog(@"新闻列表获取出错");
            //如果是刷新
            [self doneLoadingTableViewData];
            
            if ([Config Instance].isNetworkRunning == NO) {
                return;
            }
            isLoading = NO;
            if ([Config Instance].isNetworkRunning) {
                [Tool ToastNotification:@"错误 网络无连接" andView:self.view andLoading:NO andIsBottom:NO];
            }
        }];
        isLoading = YES;
        [self.tableNews reloadData];
    }
    //如果没有网络连接
    else
    {
        NSString *value = [Tool getCache:5 andID:self.catalog];
        if (value) {
            NSMutableArray *newNews = [Tool readStrNewsArray:value andOld:news];
            [self.tableNews reloadData];
            isLoadOver = YES;
            [news addObjectsFromArray:newNews];
            [self.tableNews reloadData];
            [self doneLoadingTableViewData];
        }
    }
}

分析一下这里面的代码:

首先是做一个网络连接判断,在开源中国iOS客户端学习——(六)网络连接检测一文中介绍了,作者并不是用这种方法来判断,而是使用getPath:parameters:success:failure:来判断网络的连接,方法使用AFHTTPRequestOperation和“PATCH”请求HTTP客户端操作队列,使用到了block块(iOS 4.0+特性),URL请求成功执行success块里操作,这里面block块没有返回值,接受两个参数,创建请求操作和响应数据请求,URL请求失败执行failure里面的方法,这个block块里仍没有返回值,接受两个参数创建请求操作和NSError对象,描述网络或解析错误状况;


 if()中的方法[Config Instance].isNetworkRunning==YES的,如果程序加载或者已经加载完毕什么也不返回,如果程序没有加载数据,将数据列表数量显示为0,接下来是在switch()中,根据使用者选择设置不同API接口(下图),然后就是解析显示数据信息,显示在视图中;

  

在AFNetwork 文件夹中,作者自己添加了一个AFOSCClient类,该类继承AFHTTPClient,又设计了一个sharedClient的类方法,从返回的结果可以推测出它是通过API请求返回json类型的数据,具体什么作用还没看出来;


[Tool getOSCNotice2:operation.responseString];是封装在在Tool类中的解析获取的XML的文件


URL请求成功,还做了一个程序异常处理,防止请求数据过成功程序异常崩溃

 关于@try @catch @finally异常处理的使用:


@try
{
//执行的代码,其中可能有异常。一旦发现异常,则立即跳到catch执行。否则不会执行catch里面的内容
}
@catch
{
//除非try里面执行代码发生了异常,否则这里的代码不会执行
}
@finally
{
//不管什么情况都会执行,包括try catch 里面用了return ,可以理解为只要执行了try或者catch,就一定会执行 finally
}


如果URL请求的数据出错,则反应网络不连通,数据不能加载,则弹出GCDiscreetNotificationView提示视图  提示网络错误;


postPath:parameters:success:failure:方法在程序中使用举例:

FriendsView.m

-(void)reload:(BOOL)noRefresh
{
    if (isLoadOver) {
        [self doneLoadingTableViewData];
        return;
    }
    
    [[AFOSCClient sharedClient] postPath:api_friends_list 
            parameters:[NSDictionary dictionaryWithObjectsAndKeys:segement.selectedSegmentIndex == 0 ? @"1" : @"0",@"relation",
                        [NSString stringWithFormat:@"%d", friends.count/20],@"pageIndex",
                        @"20",@"pageSize",
                        [NSString stringWithFormat:@"%d", [Config Instance].getUID],@"uid",nil] success:^(AFHTTPRequestOperation *operation, id responseObject) {
                
                if (!noRefresh) {
                    [self clear];
                }
                
                [self doneLoadingTableViewData];
                isLoading = NO;
                NSString *response = operation.responseString;
                [Tool getOSCNotice2:response];
                @try {
                    
                    TBXML *xml = [[TBXML alloc] initWithXMLString:response error:nil];
                    TBXMLElement *root = xml.rootXMLElement;
                    //显示
                    TBXMLElement *_friends = [TBXML childElementNamed:@"friends" parentElement:root];
                    if (!_friends) {
                        isLoadOver = YES;
                        [self.tableFriends reloadData];
                        return;
                    }
                    TBXMLElement *first = [TBXML childElementNamed:@"friend" parentElement:_friends];
                    if (first == nil) {
                        [self.tableFriends reloadData];
                        isLoadOver = YES;
                        return;
                    }
                    NSMutableArray *newFriends = [[NSMutableArray alloc] initWithCapacity:20];
                    TBXMLElement *name = [TBXML childElementNamed:@"name" parentElement:first];
                    TBXMLElement *userid = [TBXML childElementNamed:@"userid" parentElement:first];
                    TBXMLElement *portrait = [TBXML childElementNamed:@"portrait" parentElement:first];
                    TBXMLElement *expertise = [TBXML childElementNamed:@"expertise" parentElement:first];
                    TBXMLElement *gender = [TBXML childElementNamed:@"gender" parentElement:first];
                    Friend *f = [[Friend alloc] initWithParameters:[TBXML textForElement:name] andUID:[[TBXML textForElement:userid] intValue] andPortrait:[TBXML textForElement:portrait] andExpertise:[TBXML textForElement:expertise] andMale:[[TBXML textForElement:gender] intValue] == 1];
                    if (![Tool isRepeatFriend: friends andFriend:f]) {
                        [newFriends addObject:f];
                    }
                    while (first) {
                        first = [TBXML nextSiblingNamed:@"friend" searchFromElement:first];
                        if (first) {
                            name = [TBXML childElementNamed:@"name" parentElement:first];
                            userid = [TBXML childElementNamed:@"userid" parentElement:first];
                            portrait = [TBXML childElementNamed:@"portrait" parentElement:first];
                            expertise = [TBXML childElementNamed:@"expertise" parentElement:first];
                            gender = [TBXML childElementNamed:@"gender" parentElement:first];
                            f = [[Friend alloc] initWithParameters:[TBXML textForElement:name] andUID:[[TBXML textForElement:userid] intValue] andPortrait:[TBXML textForElement:portrait] andExpertise:[TBXML textForElement:expertise] andMale:[[TBXML textForElement:gender] intValue] == 1];
                            if (![Tool isRepeatFriend:friends andFriend:f]) {
                                [newFriends addObject:f];
                            }
                        }
                        else
                            break;
                    }
                    if (newFriends.count < 20) {
                        isLoadOver = YES;
                    }
                    
                    [friends addObjectsFromArray:newFriends];
                    [self.tableFriends reloadData];
                    
                }
                @catch (NSException *exception) {
                    [NdUncaughtExceptionHandler TakeException:exception];
                }
                @finally {
                    [self doneLoadingTableViewData];
                }
                
            } failure:^(AFHTTPRequestOperation *operation, NSError *error) {
               
                NSLog(@"好友列表获取出错");
                
                [self doneLoadingTableViewData];
                isLoading = NO;
                if ([Config Instance].isNetworkRunning) {
                    [Tool ToastNotification:@"错误 网络无连接" andView:self.view andLoading:NO andIsBottom:NO];
                }
                
            }];
    
    isLoading = YES;
    [self.tableFriends reloadData];
}

这个方法和getPath:parameters:success:failure:不同的在于请求方式是POST请求,可以向服务器里提交数据;




评论 5
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值