0

I am trying to retrieve some data from server using some sample code as follows. However it's giving me unpredictable results. I am not sure that is because the block is getting deallocated while in side the loop or getting overwritten in memory. Basically the data does not tally with index I expect.

-(void)retrieveSomeStuff {

    for (int i = 0 ; i < items.count; i++)
    {
        [self retrieveDataForIndex:i
                 completionHandler:^(NSDictionary *data, NSError *error) {


                 }];

    }
}

-(void) retrieveDataForIndex:i completionHandler:(void(^)(NSDictionary *,NSError*) completionHandler {

    [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError) {
        completionHandler(data,connectionError);
    }

}

What is the best way handle this kind of scenario ?

rustylepord
  • 5,681
  • 6
  • 36
  • 49
  • Still using MMM instead of ARC? – Lord Zsolt Mar 19 '15 at 06:31
  • you should create only one operation queue if you want to deal one by one. like static NSOperationQueue *queue;if(!queue)queue = [[NSOperationQueue alloc] init];queue.maxConcurrentCount = 1;then sendAsynchronousRequest – Suen Mar 19 '15 at 06:35
  • Your code does not do anything in the block. What is it that you want to show doesn't work? – newacct Mar 19 '15 at 19:16
  • Did you manage to solve this @rustylepord? I am facing the same issue. – KarenAnne Mar 23 '17 at 02:46

1 Answers1

-1

To avoid deallocation you have to copy the block inside the method "retrieveDataForIndex". Please see modified below.

typedef void(^CompletionHandler)(NSData * data, NSError * error);

-(void) retrieveDataForIndex:(NSInteger)i completionHandler:(CompletionHandler)Completion
{
   CompletionHandler _completionHandler = [Completion copy];
   NSURLRequest * request = [NSURLRequest requestWithURL:[NSURL URLWithString:@"https://www.google.co.in"]];

 [NSURLConnection sendAsynchronousRequest:request queue:[[NSOperationQueue alloc] init] completionHandler:^(NSURLResponse *response, NSData *data, NSError *connectionError)
 {
     _completionHandler(data, connectionError);
     [_completionHandler release];
 }];
}

-(void)retrieveSomeStuff
{
    for (int i = 0 ; i < 10; i++)
    {
      [self retrieveDataForIndex:i completionHandler:^(NSData *data, NSError *error)
      {
         NSLog(@"\nData Received");
      }];
    }
}
Nitheesh George
  • 1,357
  • 10
  • 13
  • Isn't "CompletionHandler _completionHandler" variable gets overwritten after one iteration ? – rustylepord Mar 19 '15 at 06:59
  • 1
    No since we creating a new copy of the block each time using the method "copy" and this new block address is used with in the completion block of "sendAsynchronousRequest". This is how "sendAsynchronousRequest" also does when you pass a block to it. – Nitheesh George Mar 19 '15 at 07:09
  • This copy is completely unnecessary. If `Completion` is used directly in the block passed to the operation queue, then if that block ever gets copied (which it must in order for it to be stored and executed asynchronously), it will retain all variables of object-pointer type and copy all variables of block-pointer type it captures. – newacct Mar 19 '15 at 19:14