I have the following code inside a class (static method) which I call to get data from an API. I decided to make this a static method just so I can reuse it on some other parts of the app.
+ (NSArray*) getAllRoomsWithEventId:(NSNumber *)eventId{
NSURL *urlRequest = [NSURL URLWithString:[NSString stringWithFormat:@"http://blablba.com/api/Rooms/GetAll/e/%@/r?%@", eventId, [ServiceRequest getAuth]]];
NSMutableArray *rooms = [[NSMutableArray alloc] init];
NSURLRequest *request = [NSURLRequest requestWithURL:urlRequest];
AFJSONRequestOperation *operation = [AFJSONRequestOperation JSONRequestOperationWithRequest:request success:^(NSURLRequest *request, NSHTTPURLResponse *response, id JSON) {
NSLog(@"Response of getall rooms %@", JSON);
NSArray *jsonResults = (NSArray*)JSON;
for(id item in jsonResults){
Room* room = [[Room alloc]init];
if([item isKindOfClass:[NSDictionary class]]){
room.Id = [item objectForKey:@"Id"];
room.eventId = [item objectForKey:@"EventId"];
room.UINumber = [item objectForKey:@"RoomUIID"];
[rooms addObject:room];
}
}
} failure:^(NSURLRequest *request, NSHTTPURLResponse *response, NSError *error, id JSON){
NSLog(@"Error");
}];
[operation start];
[operation waitUntilFinished];
return rooms;
}
Now my issue is, whenever I call this in a ViewController (ViewDidLoad method). The static method will run till the end and will return null on the rooms, but the Nslog will display the "Success" block Nslog a few seconds after. Now I understand that this is asynchronous so it doesn't wait for the success block to execute before it reaches the "return rooms;" line. With all that said, I need some advice as to how to handle this, like maybe a progress bar or something like that? Or something that delays it? I'm not really sure if that's the reight way or if it is, I am not sure how to do it.
Any advice is very much appreciated. Thank you!
AFNetworking is built around asynchronicity—starting a request, and then executing some piece of code once that request has finished.
waitUntilFinished
is an anti-pattern, which can block the user interface.
Instead, your method should have no return type (void)
, and have a completion block parameter that returns the serialized array of rooms:
- (void)allRoomsWithEventId:(NSNumber *)eventId
block:(void (^)(NSArray *rooms))block
{
// ...
}
See the example app in the AFNetworking project for an example of how to do this.