我在[self userLoggedIn]
区域内调用withBlock
时遇到问题。它被调用,但它不显示TITHomeViewController。如果我将它移动到块的下方和外部,那么它可以正常工作。显然,我希望从withBlock
内部调用它,因为它是异步REST请求的完成处理程序。
- (void)doAuth
{
// Call the Facebook API /me method
[FBRequestConnection startForMeWithCompletionHandler:
^(FBRequestConnection *connection, id result, NSError *error)
{
// Populate global Facebook user info
self.fbAccessToken = [[[FBSession activeSession] accessTokenData] accessToken];
self.fbUserID = [result objectForKey:@"id"];
// Authenticate with the Titter API
[self callAPI:@"auth" withBlock:^(NSDictionary *jsonData) {
NSString *_id = [jsonData objectForKey:@"_id"];
if (_id != nil) {
self.userID = _id;
[self userLoggedIn];
}
}];
}];
}
- (void)userLoggedIn
{
// Display the home view.
self.window.rootViewController = [[TITHomeViewController alloc] initWithNibName:@"TITHomeViewController" bundle:nil];
}
- (void)callAPI:(NSString *)path withBlock:(void (^)(NSDictionary *jsonData))block
{
// Initialize the API callback URL using global root and given path
NSURL *url = [NSURL URLWithString:[NSString stringWithFormat:@"%@%@", apiRoot, path]];
// The Titter API requires an authorization header formatted as [userID]@[accessToken]
NSString *authorizationHeader = [NSString stringWithFormat:@"%@@%@", self.fbUserID, self.fbAccessToken];
// Create the request and add our authorization header
NSMutableURLRequest *restRequest = [[NSMutableURLRequest alloc] initWithURL:url];
[restRequest addValue:authorizationHeader forHTTPHeaderField:@"authorization"];
// Queue required for calling sendAsynchronousRequest
NSOperationQueue *queue = [[NSOperationQueue alloc] init];
// Make an asynchronous request to our API and if there is no errors, return formatted JSON data to the passed block.
[NSURLConnection
sendAsynchronousRequest:restRequest
queue: queue
completionHandler:^(NSURLResponse *response,
NSData *data,
NSError *error) {
if ([data length] >0 && error == nil) {
NSLog(@"Succeeded! Data as string: %@", [NSString stringWithUTF8String:[data bytes]]);
// Convert received JSON data into a NSDictonary object.
NSDictionary *result = [NSJSONSerialization JSONObjectWithData:data options:NSJSONReadingMutableLeaves error:nil];
// Call back the block passed in.
block(result);
}
else if ([data length] == 0 && error == nil) {
NSLog(@"Nothing was downloaded.");
}
else if (error != nil) {
NSLog(@"Error = %@", error);
}
}];
}
答案 0 :(得分:2)
上面的评论帖子让你大约90%的方式! UI在主线程上运行,并且应该在UI线程上对其进行任何更新。您可以通过在主线程上调用usedLoggedIn
来解决阻塞代码:
dispatch_async(dispatch_get_main_queue(), ^{
[self userLoggedIn];
});
值得注意的是,可能在块中使用self
遇到问题:如果self
消失,此块将失败。在这个用例中,这可能不是问题。你没有提到这段代码来自哪个类:如果它来自视图控制器,那么可以安全地假设它不会去任何地方。但是,如果它是一个辅助对象或类似的东西,它可能会在请求URL时(或在该逻辑中的某个位置)从你的下方消失。通常的做法是创建一个对self
的弱引用,以便在块内使用,如下所示:
// Outside the block
MyViewController __weak *weakSelf = self;
// Inside the block
[weakSelf userLoggedIn];