IOS 回调函数实现方法

来源:互联网 发布:ben carson 知乎 编辑:程序博客网 时间:2024/06/11 21:32

IOS中实现回调的三种方式

经常使用到的两种类
   业务逻辑类:控制主要的业务逻辑 数据获取和加工
         
 工具类:进行网络连接 获取网络资源类耗时操作等

1.协议+代理


UtilNetWork.h 文件
@protocol GetDataFromServerDone;

@interface UtilNetWork : NSObject
+(
void) getJSonDataFromServer:(NSString*)query object:(id<GetDataFromServerDone>) delegate;
@end

@protocol GetDataFromServerDone
- (
void) GetJSonDataFromServer:(id) data;
@end


UtilNetWork.m  文件
#import "UtilNetWork.h"
#import
 "AFJSONRequestOperation.h"

@implementation UtilNetWork
+ (
void) getJSonDataFromServer:(NSString*)query  object:(id<GetDataFromServerDone>) delegate
{
   
 __block NSDictionary  *result = nil;
   
 NSURL *serverURL = [NSURL URLWithString:query];
   
 NSURLRequest *request = [NSURLRequest requestWithURL:serverURL];
   
   
 AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request
                                        
 success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON)
                                         {
                                             result  = (
NSDictionary *)JSON;
                                             [delegate
 GetJSonDataFromServer:result];
                                         }
                                        
 failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON)
                                         {
                                             [delegate
 GetJSonDataFromServer:nil];
                                         }];
    [operation 
 start];
}
@end 

     UtilNetWork类负责连网操作的工具类,用来从指定的服务器获得JSon 数据。
     在.h文件中定义了协议接口,任何想使用该类进行JSon获取的业务逻辑类必须要实现  GetDataFromServerDone这个协议,当从网络获取jSon数据后会回调用业务逻辑类实现的该方法。例如可以对获取到的JSon数据进行解析等。

2.使用代码块

 IOS NSFoundation类库中大量使用了代码卡,例如NSArray和NSDictionary类里用于枚举数据元素的函数,NSURLConnection类的连网操作函数等。
 我们也可以仿照其来定义自己的回调函数,把一些简单的逻辑操作封装到代码块中,当异步调用函数返回后会自动调用代码块。

 例如:

typedef void (^Success)(NSMutableArray *resultArray);
typedef void (^Faile)(NSString *errorMsg);

@interface GASSFlightPlanParse : NSObject<GetDataFromServerDone]] > 
{
   
 NSMutableArray *_flightPlanObjects;
   
 Success sucessBlock;         
   
 Faile  faileBlock;
}

@property (nonatomic,strong) NSMutableArray *flightPlanObjects;

- (
id)  initWithObjectByDate:(NSString *) date
             completionBlock:(
void(^)(NSMutableArray* resultArray)) success
                   failBlock:(
void(^)(NSString *errorMsg)) fail;
@end

    该类是一个飞行计划的解析类,用来将从服务器获得指定日期的JSon数据封装成对象存储到flightPlanObjects数组中返回给业务逻辑类。
业务逻辑类调用初始化函数时,会传入两个代码块来处理当获取成功和失败的时候的操作。
    当获取数据成功时,工具类通过调用代码块sucessBlock将数组flightPlanObjects传回给业务逻辑类;    
    当获取数据失败时,工具类会通过调用faileBlock将errorMsg传递给业务逻辑类。

下面时业务逻辑类的调用工具类的代码:
- (void) getFlightPlaneByDate
{
    [
self.searchBar setText:self.searchText];
   
 NSString *date = [self.searchText stringByReplacingOccurrencesOfString:@"-" withString:@""];
   
   
 void (^Success)(NSMutableArray *result) = ^(NSMutableArray *result)
    {
       
 dispatch_queue_t mainQueue = dispatch_get_main_queue();
       
 dispatch_async(mainQueue, ^
        {
           
 if ([result count] == 0)
            {
                [
self alterMessage:NSLocalizedString(@"NoFlightPlanData", @"")];
               
 return;
            }
           
 if (self.flightPlanObjectsArray!= nil)
            {
                [
self.flightPlanObjectsArray removeAllObjects];
               
 self.flightPlanObjectsArray = nil;
            }
            [
self.flightPlanObjectsArray addObjectsFromArray:result];
           
           
 self.selectedIndexPath = -1;
            [
self.myTableView reloadData];

        });
    };
   
   
 void (^Fail) (NSString *errorMsg) = ^(NSString *errorMsg)
    {
       
 dispatch_queue_t mainQueue = dispatch_get_main_queue();
       
 dispatch_async(mainQueue, ^{
           
            [
self  alterMessage:errorMsg];
        });
    };
   
 GASSFlightPlanParse *parse = [[GASSFlightPlanParse alloc] initWithObjectByDate:date completionBlock:Success failBlock:Fail];
    parse =
 nil
;
}

通过以上代码可以看到,当获取数据成功是Success代码块通过使用工具类传入的参数将结果保存到自己的数组里。同时,当失败的时候会在主线程中显示由工具类传入的错误消息
在这里代码块不仅封装了代码,而且还封装了数据,将业务逻辑类中的数据。


3.NSNotificationCenter
这种方法的使用比较简单,业务逻辑类只需要添加想要监听的Oberver, 然后工具类完成相应的操作后会想消息中心发送相应的消息,从而实现业务逻辑类和工具类之间的异步通信。
代码如下:
业务逻辑类:
/*****************************************************************
 *
 函数描述:
 *       
 飞行计划
 *
 *
 ******************************************************************/

- (
void) getFlightPlaneByDate
{
    [
self.searchBar setText:self.searchText];
   
 NSString *date = [self.searchText stringByReplacingOccurrencesOfString:@"-" withString:@""];
   
 GASSFlightPlanParse *parse = [[GASSFlightPlanParse alloc] initWithObject:self withDate:date];

    [[
NSNotificationCenter defaultCenter] addObserver:self
                                            
 selector:@selector(reloadPlanData:)
                                                
 name:KGetFlightPlanDataFromServer
                                              
 object:parse];
   [
UIApplication sharedApplication]. networkActivityIndicatorVisible  YES;
}
- (
void) reloadPlanData:(NSNotification *) notification
{
    [
self performSelectorOnMainThread:@selector(reloadFlightPlanData:)
                          
 withObject:notification
                       
 waitUntilDone:YES];
}
- (
void) reloadFlightPlanData:(NSNotification *) notification
{
   
 GASSFlightPlanParse *parse = (GASSFlightPlanParse *)[notification  object];
   
   
 if ([parse.flightPlanObjects count] == 0)
    {
        [
self alterMessage:@"暂无飞行计划信息,请稍后刷新!"];
       
 return;
    }
   
 if (self.flightPlanObjectsArray!= nil)
    {
        [
self.flightPlanObjectsArray removeAllObjects];
       
 self.flightPlanObjectsArray = nil;
    }
    [
self.flightPlanObjectsArray addObjectsFromArray:parse.flightPlanObjects];
    parse =
 nil;
   
    [[
NSNotificationCenter defaultCenter] removeObserver:self name:KGetFlightPlanDataFromServer object:parse];
   
   
 self.selectedIndexPath = -1;
    [
self.myTableView reloadData
];
}

工具类:
-(void) parseFlightPlanModels
{
    //Do something…………
    //.…………
    //.….
    [[
NSNotificationCenter defaultCenter] postNotificationName:KGetFlightPlanDataFromServer
                                                       
 object:self];
}

4.工具类保存业务逻辑类的指针
在工具类进行初始化时,保存业务逻辑类的对象的指针,但相应操作完成后调用业务逻辑类的相关方法。
- (id)  initWithObject:(GASSMasterViewController*)controller withDate:(NSString *) date;

总结:
1.以上四种方法是IOS开发过程中经常用到的异步函数实现回调的方法,其中前三种是推荐使用的,第四种代码的耦合性太高,最好不用。
2.通过比较这前三种的实现代码可以发现,代码块的方式比较简洁,NotificationCenter的方式比较好理解简单易容,协议+代理的方式
  适合用于比较负责的业务逻辑。
3.在使用以上的代码模式类构建应用的时候一定要注意的问题是,工具类尤其是连网操作往往会在非UI线程中去执行,而当这样的操作执行
  完毕后往往会执行一些与UI相关的操作,所以一定要确保这些操作要在主线程去执行,否则会出现一些意想不到的错误。
4.当代码块被引入IOS后,苹果官方文档鼓励使用代码块来实现异步操作,这样比使用代理的效率更高。

	
				
		
原创粉丝点击