If I have a for loop that uses Obj-C blocks, how can I determine the last iteration?

I have a simple class that provides a method that makes several server calls to retrieve object data for a list of object identifiers. This method lists through the list of object identifiers and makes individual server calls, shown below ...

@implementation MyClass

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {

    typeof(self) __weak blockSelf = self;
    for(NSString *objectID in objectIDs) {
        [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
            if(objectID == [objectIDs lastObject]) {  //<---will this work?
                [blockSelf.delegate finishedFetching]; 
            }
        }];
    }
}

- (void)fetchObjectDataForObjectID:(NSString*)objectID
                  withSuccessBlock:(void (^)())successBlock {

    void (^successWrapperBlock)(void) = ^{

        //Some processing of returned data is done here

        if(successBlock) {
            successBlock();
        }
    };

    [HTTPClient fetchObjectDataWithObjectID:objectID
                            withSuccessBlock:successWrapperBlock
                                failureBlock:nil];
}

@end

... I'm trying to find a better way to check if the latter is running successBlock, so I can tell the delegate that he has finished receiving the data. I have a comment in the code "<--- Will this work?" noting the statement that it does the check, but it does not feel safe for me, since the block is asynchronous, and if(objectID == [objectIDs lastObject])may be true when the first successBock is executed.

, successBlock? !

+4
6

(objectID == [objectIDs lastObject]) , , . , objectIDs (, , ), :

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {

    typeof(self) __weak blockSelf = self;
    NSArray *copiedIDs = [objectIDs copy];

    for(NSString *objectID in copiedIDs) {
        [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
            if(objectID == [copiedIDs lastObject]) {
                [blockSelf.delegate finishedFetching]; 
            }
        }];
    }
}

:

  • .
  • , , .

, :

  • , , @ChrisH. , , , .
  • . lastObject.
    • , , , . , , , . , , , . , . .

, ( @ChrisH copy):

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {

    typeof(self) __weak blockSelf = self;
    NSArray *copiedIDs = [objectIDs copy];
    __block NSUInteger count = [copiedIDs count];

    for(NSString *objectID in copiedIDs) {
        [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
            if(--count == 0) {
                [blockSelf.delegate finishedFetching]; 
            }
        }];
    }
}

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {

    typeof(self) __weak blockSelf = self;
    NSArray *copiedIDs = [objectIDs copy];
    id lastObject = [copiedID lastObject];

    for(NSString *objectID in copiedIDs) {
        [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
            if(objectID == lastObject) {
                [blockSelf.delegate finishedFetching]; 
            }
        }];
    }
}
+4

:

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs {

    typeof(self) __weak blockSelf = self;

    __block int c = [objectIDs count];

    for (NSString *objectID in objectIDs) {

        [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{

            if (--c == 0) {
                [blockSelf.delegate finishedFetching]; 
            }

        }];
    }
}

, , , .

+3

, , objectIDs , - :

typeof(self) __weak blockSelf = self;
id last = [objectIDs lastObject];
for(NSString *objectID in objectIDs) {
    [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
        if(objectID == last) {
            [blockSelf.delegate finishedFetching]; 
        }
    }];
}

for:

typeof(self) __weak blockSelf = self;
NSUInteger count = objectIDs.count;
for(NSUInteger i = 0; i < count; i++) {
    NSString *objectID = objectIDs[i];
    [self fetchObjectDataForObjectID:objectID withSuccessBlock:^{
        if(i == count - 1) {
            [blockSelf.delegate finishedFetching]; 
        }
    }];
}
+2

.

- , . - , int, . @ChrisH.

, , - . , , GCD, .

GCD , , . - - , , .

[ , !]

for :

dispatch_source_t counter = dispatch_source_create (DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, some_queue);

some_queue , dispatch_get_main_queue().

, , :

NSUInteger maxCount = objectIDs.count; // number of items to process
dispatch_source_set_event_handler(counter, ^{
                                              if (dispatch_source_get_data(counter) == maxCount)
                                                [blockSelf.delegate finishedFetching];
                                            }
                                 );

, , , , , , .

, "" 1 :

dispatch_source_merge_data(counter, 1);

ARC 10.8+, counter, , dispatch_release . , , ; -)

:

- (void)fetchObjectsFromServerWithObjectIDs:(NSArray*)objectIDs
{
   dispatch_source_t counter = dispatch_source_create(DISPATCH_SOURCE_TYPE_DATA_ADD, 0, 0, some_queue);

   NSUInteger maxCount = objectIDs.count; // number of items to process
   dispatch_source_set_event_handler(counter,
                                     ^{
                                         if (dispatch_source_get_data(counter) == maxCount)
                                            [blockSelf.delegate finishedFetching];
                                      });

   typeof(self) __weak blockSelf = self;
   for(NSString *objectID in objectIDs)
   {
      [self fetchObjectDataForObjectID:objectID withSuccessBlock:
       ^{
          dispatch_source_merge_data(counter, 1);
        }];
   }
}     

HTH

+2

, ( ) , .

, , , . NSOperation GCD, .

ID. fetchObjectDataForObjectID, , .

NSOperation *lastOp = [NSBlockOperation blockOperationWithBlock:^{
    [delegate finishedFetching];
}]

. lastOp .

GCD , NSOperation. GCD - C-, , imho, Objective-C .

+1

[blockSelf.delegate finishedFetching]; for, ? , .

0

All Articles