0

我正在使用 MKNetworkKit 库对服务器进行 REST 调用。当用户想要收藏或不收藏某张照片时,就会调用这个特定的片段集。如果我们只为单张照片设置最喜欢的标志,那么它是非常直接的 Objective-c 块代码。但是,我在 GUI 中实现了多选机制,以便用户可以选择多张照片并同时将它们全部收藏。

我为此编写的函数工作得很好,但对我来说感觉不是很干净。

我不喜欢的:

  • 使用块计数器跟踪所有回调。我想知道是否有更优雅的方式来处理这个问题。

  • 两个完成块中存在相同的代码。然而,这正是 MKNetworkKit 的使用方式(一个代表成功,一个代表错误)。我想如果我把它作为一个实例方法,我可以通过调用另一个 i-method 来处理它,但这似乎和所有设置一样混乱。我想把它作为一个方便的类方法实用程序。

建议?

+(BOOL)updateAssets:(NSArray*)assets
         isFavorite:(BOOL)isFavorite
         completion:(MyAssetCompletion)completion // (BOOL success)
{

    assert(assets);
    if (assets == nil || assets.count == 0) return NO;

    __block BOOL bError = NO;
    __block NSInteger counter = 0;  // Use a counter to track number of completed REST calls
    for(MyAsset *asset in assets){
        MyUpdateAssetForm *form = [[MyUpdateAssetForm alloc] init];
        form.isPrivate = isFavorite ? @(1) : @(0);
        [[MyRESTEngine sharedInstance] updateAssetWithUUID:asset.UUID
                                                     withForm:form
                                              completionBlock:^{
                                                  counter++;
                                                  if(counter == assets.count){
                                                      completion(bError == NO);
                                                  }
                                              } errorBlock:^(NSError *error, NSString *additionalInfo) {
                                                  bError = bError || YES;
                                                  counter++;
                                                  if(counter == assets.count){
                                                      completion(bError == NO);
                                                  }
                                              }];
    }
    return YES;
}
4

1 回答 1

0

你可以试试这个(未经测试):(
顺便说一下,你当前的实现不是线程安全的,因为计数器可能以非原子方式从一个以上的线程递增)
@see NSConditionLock

- (BOOL) updateAssets:(NSArray*)assets
           isFavorite:(BOOL)isFavorite
           completion:(bool_block_t)completion
{
    assert(assets && [assets count]);

    __block NSMutableArray* failed = [NSMutableArray new];
    __block NSConditionLock* lock = [[NSConditionLock alloc] initWithCondition:[assets count]];
    dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0),
                   ^{
                       [lock lockWhenCondition:0];
                       completion([failed count] == 0);
                   });
    NSNumber* val = (isFavorite ? @1 : @0);
    for (MyAsset* asset in assets) {
        MyUpdateAssetForm* form = [[MyUpdateAssetForm alloc] init];
        form.isPrivate = val;
        [self updateAssetWithUUID:asset.UUID
                         withForm:form
                  completionBlock:^{[lock unlockWithCondition:[lock condition] - 1];}
                       errorBlock:^(NSError *error, NSString *additionalInfo)
         {
             [lock lock];
             [failed addObject:asset];
             [lock unlockWithCondition:[lock condition] - 1];
         }];
    }
    return YES;
}
于 2013-04-04T20:23:41.740 回答