Search code examples
iphoneobjective-ccocoa-touchnetwork-programmingasihttprequest

Convert network request from synchronous to asynchronous


I'm currently doing a synchronous network request to load my app which is not the best way as it blocks the UI. I'm also using ASIHTTPRequest. I understand I can just change the line from synchronous to asyncronous, but I think I need to setup a block so that I can trigger the table to reload once the async is completed.

The initial ViewController of my app:

- (void)fetchAppointmentsForVisibleDate {
    self.appointmentArray = [DrChronoDataSource getTodayData:self.visibleDate];

    NSMutableArray *array = [NSMutableArray arrayWithCapacity:50];
    for (NSDictionary *appointment in self.appointmentArray)
    {
        [array addObject: [NSString stringWithFormat:@"%@: %@", [appointment objectForKey:@"scheduled_time"], [appointment objectForKey:@"patient"]]];
    }
    self.listData = array;
    [self.appointmentTableView reloadData];
}

In my app's dataSource class:

+ (NSMutableArray*)getTodayData:(NSDate*)today
{
        NSURL *url = myURL here 
        ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
        [request setPostValue:[dateFormat stringFromDate:today] forKey:@"target_date"];

        [request startSynchronous];

        NSError *error = [request error];
        NSString *responseString;
        if (!error) {
            responseString = [request responseString];
        } else {
            return NULL;
        }
        return [responseString JSONValue];
}

Solution

  • + (void) getTodayData:(NSDate*)today callback:(void (^) (NSError * error, NSMutableArray * array)) callback
    {
            NSURL *url = myURL here 
            ASIFormDataRequest *request = [[ASIFormDataRequest alloc] initWithURL:url];
            [request setPostValue:[dateFormat stringFromDate:today] forKey:@"target_date"];
            [request setCompletionBlock:^{
                callback(nil, [responseString JSONValue]);
            }];
            [request setFailBlock:^{
               callback([request error], nil);
            ];
            [request startAsynchronous];
    }
    
    - (void)fetchAppointmentsForVisibleDate {
        [DrChronoDataSource getTodayData:self.visibleDate callback:^(NSError *error, NSMutableArray *data))callback {
            if (!error) {
                self.appointmentArray = [data retain];
                NSMutableArray *array = [NSMutableArray arrayWithCapacity:50];
                for (NSDictionary *appointment in self.appointmentArray)
                {
                    [array addObject: [NSString stringWithFormat:@"%@: %@", [appointment objectForKey:@"scheduled_time"], [appointment objectForKey:@"patient"]]];
                }
                self.listData = array;
                [self.appointmentTableView reloadData];
            }
            else 
                NSLog(@"%@", error.description);
        }];
    }  
    

    You need to change the method so that you will be notified when the download has been completed, using the block. The ASI Completion & Failure blocks need to be set. Please rename them as I have not checked the code and I am sure I have spelt the methods wrong.