2014-02-16 265 views
1

我想初始化一个模型,让模型做一些异步的东西,并提交一个新的viewcontroller一旦完成。但是,我如何等待两个异步方法完成,以及如何设置回调方法?等待两种异步方法完成

在我StartViewController.m:

-(void)openArticle 
{ 
    article = [Article initWithObject:someObject]; 
    article.callback = changeView; 
} 

-(void)changeView 
{ 
[self presentViewController:someController]; 
} 

在我ArticleModel.m:

-(void)initWithObject:someObject 
{ 
    [self loadImage] 
    [self geoCode] 
} 

-(void)loadImage 
{ 
    runAsyncMethod: success:^() // This one is actually a AFNetworking setImageWithURLRequest 
} 

-(void)geoCode 
{ 
    runAnotherAsyncMethod: success:^() // This one is actually a geocodeAddressString operation 
} 

回答

3

可以使用dispatch_group小号

- (void)initWithObject:(id)someObject 
{ 
    self = [super init]; 
    if (self) { 
    self.dispatch_group = dispatch_group_create(); 

    [self loadImage] 
    [self geoCode] 

    dispatch_group_notify(self.dispatch_group, dispatch_get_main_queue(), ^{ 
     NSLog(@"Push new view controller"); 
    }); 
    } 
    return self; 
} 

- (void)loadImage 
{ 
    dispatch_group_enter(self.dispatch_group); 

    __weak __typeof(self) weakSelf = self; 
    runAsyncMethod: success:^{ 
    __typeof(weakSelf) strongSelf = weakSelf; 
    if (strongSelf.dispatch_group) { 
     dispatch_group_leave(strongSelf.dispatch_group); // You need to ensure that this is called in both success and failure 
    } 
    } 

} 

- (void)geoCode 
{ 
    dispatch_group_enter(self.dispatch_group); 

    __weak __typeof(self) weakSelf = self; 
    runAnotherAsyncMethod: success:^{ 
    __typeof(weakSelf) strongSelf = weakSelf; 
    if (strongSelf.dispatch_group) { 
     dispatch_group_leave(strongSelf.dispatch_group); 
    } 
    } 
} 
+0

通过引用self作为'__weak'变量来避免保留周期的积分 – jackslash

+0

谢谢。但是,如果我的一个AsyncMethod失败,我该如何处理错误?导致dispatch_group_notify()在成功和失败时被调用。 – fabian

1

你做等待。如果你等待,它不是异步的!如果您要等待,您将会失去整个异步点。

你要做的是,当你的success处理程序被调用时,你走出主线程(以防万一你在后台线程上被回调),现在做你需要做的任何事情。换句话说,你只要让你的success处理程序在被调用的时候被调用。

在你的情况,你可能想链上的事情你想做的事:

  • 呼叫loadImage

  • 在其回调,调用geoCode

  • 在其回调,一步进入主线程并呈现新的视图控制器。

+0

您可能希望异步推出两个请求,以获得一点点的时间实现这一目标。有两个请求启动异步允许他不要等待一种方法和另一种。当然,如果它们完全不相关,并且不是免费的,那就行得通了。 – jbouaziz

+0

是的,@ jbouaziz,但我只是不想陷入'dispatch_group'的复杂性。我很高兴你添加了一个答案显示! – matt

1

您可以使用dispatch_group这样,当一个方法结束,它只是叶子群组。我自己使用类似的代码,它的作用就像一个魅力。

- (void)initWithObject:someObject { 

    // Create a dispatch group 
    dispatch_group_t group = dispatch_group_create(); 
    [self loadImageWithDispatchGroup:group]; 
    [self geoCodeWithDispatchGroup:group]; 

    // Here we wait for all the requests to finish 
    dispatch_group_notify(group, dispatch_get_main_queue(), ^{ 
     // Do whatever you need to do when all requests are finished 
    }); 
} 

- (void)loadImageWithDispatchGroup:(dispatch_group_t)group { 
    dispatch_group_enter(group); 
    runAsyncMethod: success:^() // This one is actually a AFNetworking setImageWithURLRequest 
    // In your success or failure AFNetworking method, call this as soon as the request ended 
    dispatch_group_leave(group); 
} 

- (void)geoCodeWithDispatchGroup:(dispatch_group_t)group { 
    dispatch_group_enter(group); 
    runAnotherAsyncMethod: success:^() // This one is actually a geocodeAddressString operation 
    // In your success async geocode callback method, call this as soon as the request ended 
    dispatch_group_leave(group); 
}