Facebook iOS SDK 3.5.1:openActiveSessionWithReadPermissions – 完成处理程序调用两次

我有一个共享链接的按钮。 我基本上使用了两个调用: openActiveSessionWithReadPermissionsrequestNewPublishPermissions

这是按钮动作:

 - (IBAction) shareFacebookButtonAction:(id)sender if (![[FBSession activeSession] isOpen]) { NSArray *permissions = @[@"read_friendlists", @"email"]; [FBSession openActiveSessionWithReadPermissions:permissions allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState state, NSError *error) { if (FB_ISSESSIONOPENWITHSTATE([session state])) { [self _prepareShare]; } else { // show alert view with error } }]; } else { [self _prepareShare]; } } 

如果没有在会话中找到任何权限,我要求获得发布许可

 -(void) _prepareShare; { if ([FBSession.activeSession.permissions indexOfObject:@"publish_actions"] == NSNotFound) { [FBSession.activeSession requestNewPublishPermissions: [NSArray arrayWithObject:@"publish_actions"] defaultAudience:FBSessionDefaultAudienceFriends completionHandler:^(FBSession *session, NSError *error) { if (!error) { [self _share]; } else { //error } }]; } else { [self _share]; } } 

_share只发帖

 -(void) _share; { NSMutableDictionary *params_dict = [NSMutableDictionary dictionary]; // setting some params [FBRequestConnection startWithGraphPath:@"me/feed" parameters:params_dict HTTPMethod:@"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { if (result) { // sharing succedeed, do something } else if (error) { //sharing failed, do something else } }]; } 

我第一次尝试共享(已经登录过iOS6和已授权的应用程序) openActiveSessionWithReadPermissions完成处理程序被调用两次:一次使用FBSessionStateOpen,一次使用FBSessionStateOpenTokenExtended(来自openSessionForPublishPermissions调用)。 因此, _share也被调用两次,第一次在_prepareShareelse部分(如果我已经拥有发布权限),第二次在openSessionForPublishPermissions的完成处理程序中。 所以我在Facebook墙上有一个双重post,这是我第一次分享应用程序。 我还有一份关于FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed的崩溃报告FBSession: It is not valid to reauthorize while a previous reauthorize call has not yet completed (我无法再次发生这种情况)。

处理这种情况的正确方法是什么?

似乎在设计上,Facebook SDK保留了对块处理程序的引用,即使在它们被调用之后也是如此。 因此,在调用openActiveSessionWithReadPermissions时 ,如果会话状态发生更改,则可以多次调用完成处理程序。 在这里查看Facebook对此问题的评论 。

作为一种解决方法,您可能希望实现自己的机制,以确保只处理一次处理程序:

 __block FBSessionStateHandler runOnceHandler = ^(FBSession *session, FBSessionState status, NSError *error) { /* YOUR CODE HERE */ }; ... [FBSession openActiveSessionWithReadPermissions:YOUR_PERMISSIONS allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState status, NSError *error) { if (runOnceHandler) { runOnceHandler(session, status, error); runOnceHandler = nil; } } ]; 

你可以用它

 - (IBAction)facebookBasti:(id)sender { if(FBSession.activeSession.isOpen){ [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary *user, NSError *error) { if (!error) { NSLog(@" Email = %@",[user objectForKey:@"email"]); } }]; NSLog(@"POST TO WALL -- %@",FBSession.activeSession.accessToken); [self publishFacebook]; } else { // try to open session with existing valid token NSArray *permissions = [[NSArray alloc] initWithObjects: @"publish_actions",@"email", nil]; FBSession *session = [[FBSession alloc] initWithPermissions:permissions]; [FBSession setActiveSession:session]; if([FBSession openActiveSessionWithAllowLoginUI:NO]) { // post to wall [[FBRequest requestForMe] startWithCompletionHandler:^(FBRequestConnection *connection, NSDictionary *user, NSError *error) { if (!error) { NSLog(@" Email = %@",[user objectForKey:@"email"]); } }]; NSLog(@"POST TO WALL -- %@",FBSession.activeSession.accessToken); [self publishFacebook]; } else { // you need to log the user NSLog(@"login"); [FBSession openActiveSessionWithPermissions:permissions allowLoginUI:YES completionHandler:^(FBSession *session, FBSessionState state, NSError *error) { NSLog(@"POST TO WALL -- %@",FBSession.activeSession.accessToken); [self publishFacebook]; }]; } } 

}

和publishFacebook方法

  -(void)publishFacebook { NSMutableDictionary *postParams2= [[NSMutableDictionary alloc] initWithObjectsAndKeys: haberLink, @"link", @"abc.com", @"name", title, @"caption", desc, @"description", nil]; [FBRequestConnection startWithGraphPath:@"me/feed" parameters:postParams2 HTTPMethod:@"POST" completionHandler:^(FBRequestConnection *connection, id result, NSError *error) { NSString *alertText; if (error) { alertText = [NSString stringWithFormat: @"error: domain = %@, code = %d", error.domain, error.code]; } else { alertText = [NSString stringWithFormat: @"Shared Facebook"]; [[[UIAlertView alloc] initWithTitle:@"Shared Facebook" message:alertText delegate:self cancelButtonTitle:@"Ok" otherButtonTitles:nil] show]; } }]; 

}

请阅读从3.0升级到3.1 ,特别是要求单独读取和写入权限的段落。 似乎Facebook SDK并不打算以这种方式使用。

您现在需要单独请求读取和发布权限(并按此顺序)。 最有可能的是,当应用程序启动并且用户首次登录时,您将请求个性化的读取权限。稍后,如果合适,您的应用程序可以在打算将数据发布到Facebook时请求发布权限。

重要的是,您不要简单地尝试背对背地调用两个单独的方法来替换任何已弃用的函数。

我想知道你是如何设法解决这个问题的。 顺便说一下,我得到了相同的崩溃报告(FBSession:在先前的重新授权呼叫尚未完成时重新授权是无效的)。