0
-(NSMutableArray *)fetchDataForNotifications{
    __block NSMutableArray *responseArray = nil;
    NSString *requestData = [self prepareRequestJsonForNotificatios];
    NSData *postData = [requestData dataUsingEncoding:NSASCIIStringEncoding   allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
    NSString* urlString = [SERVER_URL_QA stringByAppendingString:@"/api/home/notifications"];
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setTimeoutInterval:10.0];
    [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
    [request setHTTPShouldHandleCookies:YES];
    NSOperationQueue *queue = [NSOperationQueue mainQueue];
    [NSURLConnection sendAsynchronousRequest:request queue:queue   completionHandler:^(NSURLResponse *response, NSData *dataAll, NSError *error)
     {
         NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
         long int httpResponseCode = [httpResponse statusCode];

         if (error == nil && httpResponseCode == 200 && dataAll && dataAll.length > 0){
             NoticationsModel *notificationRow = [[NoticationsModel alloc]init];

             responseArray = [NSJSONSerialization JSONObjectWithData:dataAll options:NSJSONReadingMutableContainers error:nil];
             NSLog(@"HR1 %d", responseArray.count);
             for(int i =0;i<responseArray.count;i++){
                 notificationRow.fromPhotoURL = [[responseArray objectAtIndex:i] valueForKey:@"Fromphotourl"];
                 notificationRow.notificationBody = [responseArray valueForKey:@"Body"];
                 notificationRow.updatedDate = [[responseArray objectAtIndex:i] valueForKey:@"UpdatedDate"];
                 notificationRow.fromName = [responseArray valueForKey:@"FromName"];
                 [notificationArray addObject:notificationRow];
             }
         }
         else {
             NSString* errorMessage = [NSString stringWithFormat:@"Data retrived could not be   parsed. Error code %ld", (long)error.code ];
             NSLog(@"%@",errorMessage);
         }
     }];
    NSLog(@"HR %d", responseArray.count);
    return responseArray;
}

The output in the console is:

2014-11-20 13:45:52.667 myFriday[2888:81062] HR 0
2014-11-20 13:45:52.879 myFriday[2888:81062] HR1 10

I dont understand why the count is not retaining outside the block. Any help?

albertamg
  • 28,492
  • 6
  • 64
  • 71
Vamshi Krishna
  • 979
  • 9
  • 19
  • To begin with, the completion block will not execute immediately. As you can see in the order of the logs, the `NSLog` inside the block executes after the one at the bottom. By the time the NSLog at the bottom executes the `responseArray` is still `nil`. – albertamg Nov 20 '14 at 09:15
  • I need to pass the responseArray.count to another controller(which is going as 0 now). What can be the solution?Any help? – Vamshi Krishna Nov 20 '14 at 09:29

1 Answers1

0

Use of block

You can take an advantage of block also.

Create block method to get response from server. Below I have modified method signature to call using block:

- (void) fetchDataForNotifications:(void (^)(NSMutableArray *response))block {

    __block NSMutableArray *responseArray = nil;
    NSString *requestData = [self prepareRequestJsonForNotificatios];
    NSData *postData = [requestData dataUsingEncoding:NSASCIIStringEncoding   allowLossyConversion:YES];
    NSString *postLength = [NSString stringWithFormat:@"%lu", (unsigned long)[postData length]];
    NSString* urlString = [SERVER_URL_QA stringByAppendingString:@"/api/home/notifications"];
    NSURL *url = [NSURL URLWithString:urlString];
    NSMutableURLRequest *request = [[NSMutableURLRequest alloc] init];
    [request setURL:url];
    [request setHTTPMethod:@"POST"];
    [request setHTTPBody:postData];
    [request setValue:postLength forHTTPHeaderField:@"Content-Length"];
    [request setValue:@"application/json" forHTTPHeaderField:@"Content-Type"];
    [request setTimeoutInterval:10.0];
    [request setCachePolicy:NSURLRequestReloadIgnoringCacheData];
    [request setHTTPShouldHandleCookies:YES];
    NSOperationQueue *queue = [NSOperationQueue mainQueue];

    [NSURLConnection sendAsynchronousRequest:request queue:queue   completionHandler:^(NSURLResponse *response, NSData *dataAll, NSError *error)
     {
         NSHTTPURLResponse* httpResponse = (NSHTTPURLResponse*)response;
         long int httpResponseCode = [httpResponse statusCode];

         if (error == nil && httpResponseCode == 200 && dataAll && dataAll.length > 0){
             NoticationsModel *notificationRow = [[NoticationsModel alloc]init];

             responseArray = [NSJSONSerialization JSONObjectWithData:dataAll options:NSJSONReadingMutableContainers error:nil];
             NSLog(@"HR1 %d", responseArray.count);
             for(int i =0;i<responseArray.count;i++){
                 notificationRow.fromPhotoURL = [[responseArray objectAtIndex:i] valueForKey:@"Fromphotourl"];
                 notificationRow.notificationBody = [responseArray valueForKey:@"Body"];
                 notificationRow.updatedDate = [[responseArray objectAtIndex:i] valueForKey:@"UpdatedDate"];
                 notificationRow.fromName = [responseArray valueForKey:@"FromName"];
                 [notificationArray addObject:notificationRow];
             }
         }
         else {
             NSString* errorMessage = [NSString stringWithFormat:@"Data retrived could not be   parsed. Error code %ld", (long)error.code ];
             NSLog(@"%@",errorMessage);
         }

         block(responseArray);
     }];
}

Call this method and it will wait for a block but you need to perform reload table operation on main thread.

[self fetchDataForNotifications:^(NSMutableArray *response) {

        // Perform operation on main thread.
        // Don't forget to set response array value to tableview datasource array.
        // e.g. self.tableArray = response;

        [self performSelectorOnMainThread:@selector(realoadTableData) withObject:nil waitUntilDone:YES];
}];


- (void) realoadTableData {
    [self.tableView reloadData];
}
Kampai
  • 22,848
  • 21
  • 95
  • 95
  • Isn't just easier to use `sendSynchronousRequest:returningResponse:error:` if you are going to block the thread anyway? Either way, you don't want to do it from the main thread. – albertamg Nov 20 '14 at 12:42
  • Right! it is bottleneck for both. Let me provide block solution too. – Kampai Nov 20 '14 at 13:06
  • I tried using Semaphore. Actually fetchDataForNotifications method gets called when the notifications button on screen is clicked. After using semaphore, when I click the button, nothing happens and the UI gets blocked. – Vamshi Krishna Nov 20 '14 at 13:36