I am using AFNetworking kit to develop an iOS app.
When the app is launching, it requests an access token from the server.
The code is simple as:
__block int status = 0;
[manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject)
{
...fetch access token from response json string
status = 1; //break the loop
}
failure:^(AFHTTPRequestOperation *operation, NSError *error) {
...networking error
}
and also, to make sure the other requests to the server own the access token, I have put a loop to block the thread until the server responses.
while (status == 0)
{
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode
beforeDate:[NSDate date]];
}
This worked before, until I imported a third party notification push library. And the async method:
- (void)application:(UIApplication *)application didRegisterForRemoteNotificationsWithDeviceToken:(NSData *)deviceToken
is continuing print deviceToken
request in console and the access token request never responds anything, even the server actually provides the response.
I have been stuck for day, can someone helps me?
UPDATE I have tried to comment the device token stuff, the AFNetworking request still doesn't work, no success no failure and no timeout:
UPDATE2 Clarify my question. AFHTTPRequestOperationManager
have sent a GET request to the server, and server responses. But the AFHTTPRequestOperationManager
doesn't receive it, and no success no failure callback as well.
A couple of thoughts:
If you're going to use this pattern:
you really should set status
to 1
in the error block, too; and
Apple uses distantFuture
in its examples, not date
:
[[NSRunLoop currentRunLoop] runMode:NSDefaultRunLoopMode beforeDate:[NSDate distantFuture]];
You might have something else blocking the main thread. Try putting a NSLog
inside the while
loop and see if you see that loop running. If not, then identify where you're blocking the main thread.
Needless to say, this overall pattern is inefficient. I'd suggest employing asynchronous patterns, such as adopting completion handlers in your own code:
- (void)performSomeURL:(NSString *)url completionHandler:(void (^)(NSDictionary *response, NSError *error))completionHandler{
NSDictionary *parameters = ...;
[manager GET:url parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
completionHandler(responseObject, nil);
} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
completionHandler(nil, error);
}];
}
which could be called like:
[self performSomeURL:url completionHandler:^(NSDictionary *response, NSError *error) {
// use response and error here
}];
// but not here
If you always adopt asynchronous patterns like this in all of your code, never doing anything that blocks the main thread, then not only will your code be more efficient, but you'll never have to fear about deadlocking on the main thread.