我创建了一个名为User的模型,它具有属性“name”。
我正在向facebook API发送请求(使用最新的iOS SDK),当facebook返回数据时,想法是设置我的user.name属性。
facebook将数据返回到startWithCompletionHandler
块,但我无法将此数据设置为我的用户对象,我只能访问startWithCompletionHandler
上的数据。当我尝试从块中访问数据时,我的模型返回NULL
。
当facebook请求返回时,如何填写我的模型/对象?
我目前的方法实施:
+ (void)requestUserData:(User *)userModel {
if(FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if(user.name) [self setUserData:user userModel:userModel];
}];
}
}
+ (void)setUserData:(NSDictionary<FBGraphUser> *)user userModel:(User *)userModel {
userModel.name = user.name;
}
电话:
__block User *user = [[User alloc] init];
[GFFacebookHelpers requestUserData:user];
NSLog(@"user: %@", user.name); //this part prints 2013-06-06 18:03:43.731 FacebookClassTest[74172:c07] user: (null)
感谢。
答案 0 :(得分:2)
Facebook的SDK是异步获取的,因此您编写的完成处理程序将在您的帮助程序方法返回后执行。
因此,当你的方法返回你的User对象时,逻辑上只是一个空用户(因为你已经分配/初始化它)。
当调用完成块时,该用户对象会更新,但此时,您不再在应用程序(视图控制器)中处理它。
所以这是我的建议:要么直接从视图控制器使用Facebook SDK,要么想要将所有这些逻辑保留在助手类中,然后更改它以使您的方法不返回数据,但它需要数据请求完成后将调用的块,更像是:
+ (void)requestUserDataWithCompletionHandler:(void (^)(User *user, NSError *error))handler{
if(FBSession.activeSession.isOpen) {
[[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary<FBGraphUser> *user, NSError *error) {
if(!error){
User *userData = [[User alloc] init];
userData.name = user.name;
dispatch_async(dispatch_get_main_queue(), ^{
handler(userData, nil);
});
}
else{
dispatch_async(dispatch_get_main_queue(), ^{
handler(nil, error);
});
}
}];
}
}
注意我已将dispatch_async()
中处理程序块的调用包装到主队列中,以确保您可以更新任何UI。
您的视图控制器的方法现在将如下所示:
- (void)updateStatusLabels {
if([GFFacebookHelpers isLogged]){
[GFFacebookHelpers requestUserDataWithCompletionHandler:^(User *user, NSError *error) {
if(!error){
self.fbStatus.text = user.name;
[_loginButton setTitle:@"Logout" forState:UIControlStateNormal];
}
}];
}else{
self.fbStatus.text = @"You need to login";
[_loginButton setTitle:@"Login" forState:UIControlStateNormal];
}
}