Objective-C和Multithreds中的块

时间:2014-09-18 03:00:11

标签: asynchronous objective-c-blocks grand-central-dispatch

说明: 在我的Xcode项目中,我有3个数据存储区:SFGroupsItemStore,SFFeedsItemStore,SFQuestsItemStore。所有这个类都是我的自定义类的子类,并且都是单例。 我在下一个控制器中使用的每个类:SFGroupsListViewController SFFeedsListViewController,SFQuestsListViewController。所有这个类都有方法:-downloadItems

问题: 我想创建一个控制器SFHomeViewController,它将呈现所有3个数据存储混合的表。 为了解决这个问题,我想创建聚合器SFHomeItemStore,也是单例,我希望这个类有方法-downloadItems。

所以,我已经完成了,SF HomeItemStore中有-downloadIItems的实现

1步:

- (NSArray *)downloadItemsFrom:(int32_t)from withLimit:(int)limit andDirection:(NSString *)direction{

     NSArray     *groupsItems     =     [[SFGroupsItemStore shared] downloadItems];
     NSArray     *feedsItems     =     [[SFFeedsItemStore shared] downloadItems];
     NSArray     *questsItems     =     [[SFQuestsItemStore shared] downloadItems];

     NSMutableArray     *mixedArray     =     [NSMutableArray array];

     [mixedArray addObjectsFromArray:groupsItems];
     [mixedArray addObjectsFromArray:feedsItems];
     [mixedArray addObjectsFromArray:questsItems];

     NSArray     *sortedArray     =     [mixedArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO]]];
     return sortedArray;

}

这项工作对我来说很好。

2步: 但我不喜欢方法调用-downloadItems顺序,为什么调用这个方法我需要花更多的时间 但如果我添加GCD我有问题, 现在实现方法-downloadItems是

- (NSArray *)downloadItemsFrom:(int32_t)from withLimit:(int)limit andDirection:(NSString *)direction{

     __block     NSArray     *sortedArray     =     nil;

     __block     NSArray     *groupsItems;
     __block     NSArray     *feedsItems;
     __block     NSArray     *questsItems;

     dispatch_group_t     groupedTask     =     dispatch_group_create();
     dispatch_queue_t     globalQueue     =     dispatch_get_global_queue( 0, 0 );

     dispatch_group_async( groupedTask, globalQueue, ^{
          groupsItems     =     [[SFGroupsItemStore shared] downloadItems];
     } );

     dispatch_group_async( groupedTask, globalQueue, ^{
          feedsItems     =     [[SFFeedsItemStore shared] downloadItems];
     } );

     dispatch_group_async( groupedTask, globalQueue, ^{
          questsItems     =     [[SFQuestsItemStore shared] downloadItems];
     } );

     dispatch_group_notify( groupedTask, globalQueue, ^{

          NSMutableArray     *mixedArray     =     [NSMutableArray array];
          [mixedArray addObjectsFromArray:groupsItems];
          [mixedArray addObjectsFromArray:feedsItems];
          [mixedArray addObjectsFromArray:questsItems];

          sortedArray     =     [mixedArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO]]];

     } );

     return sortedArray;

}

问题是,无论dispatch_group_notify如何,方法返回结果以及为什么数组sortedArray为空

所以,我的问题是: 我怎么做才能在dispatch_group_notify函数结束后返回结果?

1 个答案:

答案 0 :(得分:0)

您有两种选择:

  1. 如果您的方法可以阻止当前线程,那么您可以使用dispatch_group_wait
  2. 使用完成处理程序返回NSArray
  3. dispatch_group_wait

    来自文档:

      

    同步等待先前提交的块对象   完成;如果块未在指定之前完成,则返回   超时时间已过。

    你的方法看起来像这样:

    - (NSArray *)downloadItemsFrom:(int32_t)from withLimit:(int)limit andDirection:(NSString *)direction{
    
        // ... 
    
        dispatch_group_async( groupedTask, globalQueue, ^{
             groupsItems     =     [[SFGroupsItemStore shared] downloadItems];
        } );
    
        // ...
    
        dispatch_group_wait(groupedTask, DISPATCH_TIME_FOREVER);
    
        NSMutableArray     *mixedArray     =     [NSMutableArray array];
        [mixedArray addObjectsFromArray:groupsItems];
        [mixedArray addObjectsFromArray:feedsItems];
        [mixedArray addObjectsFromArray:questsItems];
    
        sortedArray     =     [mixedArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO]]];
    
        return sortedArray;
    }
    

    使用完成处理程序

    这是我喜欢的方法。

    您需要更改方法签名,以便将完成处理程序作为新参数,并返回void而不是NSArray。使用此方法,您仍然使用dispatch_group_notify

    它看起来像这样:

    - (void)downloadItemsFrom:(int32_t)from 
                    withLimit:(int)limit 
                    direction:(NSString *)direction 
         andCompletionHandler:(void (^)(NSArray*))completionHandler
    {
    
        // ... 
    
        dispatch_group_async( groupedTask, globalQueue, ^{
             groupsItems     =     [[SFGroupsItemStore shared] downloadItems];
        } );
    
        // ...
    
         dispatch_group_notify( groupedTask, globalQueue, ^{
    
              NSMutableArray     *mixedArray     =     [NSMutableArray array];
              [mixedArray addObjectsFromArray:groupsItems];
              [mixedArray addObjectsFromArray:feedsItems];
              [mixedArray addObjectsFromArray:questsItems];
    
              sortedArray     =     [mixedArray sortedArrayUsingDescriptors:[NSArray arrayWithObject:[NSSortDescriptor sortDescriptorWithKey:@"createdAt" ascending:NO]]];
    
              completionHandler(sortedArray);
         } );
    }
    

    现在调用它看起来像:

    [object downloadItemsFrom:... 
                    withLimit:... 
                     diretion:... 
         andCompletionHandler:^(NSArray *items) 
    {
    
    }];