Can Afnetworking Return Data Synchronously (Inside a Block)

Can AFNetworking return data synchronously (inside a block)?

To block the execution of the main thread until the operation completes, you could do [operation waitUntilFinished] after it's added to the operation queue. In this case, you wouldn't need the return in the block; setting the __block variable would be enough.

That said, I'd strongly discourage forcing asynchronous operations to synchronous methods. It's tricky to get your head around sometimes, but if there's any way you could structure this to be asynchronous, that would almost certainly be the way to go.

How to use AFNetworking 2.0 synchronously

You should not make an inherently asynchronous method synchronous, but instead make your call-site asynchronous as well.

That is, your method becomes asynchronous and provides a completion handler:

- (void) userWithUsername:(NSString *)username 
password:(NSString *)password
completion:(completion_handler_t)completion;

where completion_handler_t is a type definition and may be declared in the header file like this:

typedef void (^completion_handler_t)(User*, NSError*);

Note that using a typedef is optional and may make your code more comprehensible.

Then you can use it as follows:

[self userWithUsername:username 
password:password
completion:^(User* user, NSError*error){
// Check error; do something with user
...
}];

You can implement it as shown below:

- (void) userWithUsername:(NSString *)username 
password:(NSString *)password
completion:(completion_handler_t)completion
{
NSDictionary *params = @{@"email": username, @"password": password};
[[DCAPIClient sharedClient] POST:@"login" parameters:params
success:^(NSURLSessionDataTask * __unused task, id JSONResult) {
NSLog(@"JSON %@", JSONResult);
BOOL errorCode = [JSONResult objectForKey:@"error"];
if (!errorCode) {
self.username = [JSONResult objectForKey:@"name"];
// Fill the attributes
// self.email = .. a
if (completion) {
completion(theUser, nil); // completion(self, nil)??
}
} else {
if (completion) {
completion(nil, error);
}
}

} failure:^(NSURLSessionDataTask *__unused task, NSError *error) {
if (completion) {
completion(nil, error);
}
}];
}

AFNetworking to run synchronously

I want to run it synchronously to do a package download (I need to get the list of services that people will be able to choose from). How can I do this?

AFNetworking does not support sync operations.

On the other hand, you almost never want sync operations on your UI thread, because the UI would become unresponsive.

(I need to get the list of services that people will be able to choose from)

What you could do is displaying some UI hint that the list of services is being downloaded while the async operation is in progress.

Wait for AFNetworking completion block before continuing (i.e. Synchronous)

It sounds like there's a part of your app that can't run until a starting request is done. But there's also a part that can run (like the part that starts the request). Give that part a UI that tells the user that we're busy getting ready. No blocking the UI.

But if you must, and if AFNetworking doesn't provide a blocking version of a request (kudos to them for that), then you could always block the old fashioned way...

- (void)pleaseDontUseThisIdea {

__block BOOL thePopeIsCatholic = YES;
[manager GET: ....^{
// ...
thePopeIsCatholic = NO;
}];

while (thePopeIsCatholic) {}
}

Return data after AFNetworking is done

I don't think you know how Asynchronous operations work. The NSMutableArray will never be set, because it is returned synchronously.
In your case, I suggest you to work with delegates.

- (void)getTournamentsInClub:(NSString *)clubGUID withDelegateViewController:(UIViewController *)viewController completionBlock:(void (^)(NSMutableArray *result))completionBlock {
AFHTTPRequestOperationManager *manager = [AFHTTPRequestOperationManager manager];
NSMutableArray *responseArray = [[[NSMutableArray alloc] init] autorelease];
NSString *URL = [[NSString alloc]initWithFormat:@"SomeURL=%@",clubGUID];
[manager POST:URL parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {

for (id obj in responseObject) {
[responseArray addObject:obj];
}

// Request finished. Call the block.
completionBlock(responseArray);

} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
NSLog(@"Error: %@", error);
}];
}

- (void)handleClubTournaments {
GP_MobilAppDelegate *xdelegate = [[UIApplication sharedApplication] delegate];
[[TournamentsWebService sharedToursWS] getTournamentsInClub:^(NSMutableArray *result)
{
// Hide the Loading Indicator. Do something with the Result.
}];

// You can't access the result synchronously, therefore it's impossible to depend on it synchronously.
}

another way to return the data asynchronously would be blocks, similar to the AFNetworking solution.

You can read more about getting started with blocks here and how to use delegates here.



Related Topics



Leave a reply



Submit