发布前xcode自动登录中的Facebook SDK Singleton?

Posted

技术标签:

【中文标题】发布前xcode自动登录中的Facebook SDK Singleton?【英文标题】:Facebook SDK Singleton in xcode auto login before post? 【发布时间】:2012-01-30 20:25:59 【问题描述】:

按照 Facebook 教程的指示,我已经让 Facebook SDK 在 APPDelegate 中工作,但是我正在尝试将其放入单例方法中。我发现的每个教程似乎都适用于旧版本的 SDK,但我已经成功地使用了这个 http://indiedevstories.com/2011/08/30/a-facebook-reusable-class/

我遇到了两个问题,第一个发布在here 这是第二个:

我想要一个按钮来发布到 Facebook,但如果用户没有登录,那么他们需要先登录然后发布(无需先按单独的登录按钮)。 我可以正常登录,也可以正常发帖,但是我不能同时进行这两种操作。 如果未登录,post code 会显示登录屏幕,但登录后不会进入 post 屏幕。您必须再次按 post。 如果您尝试登录但已经登录,则不会发生任何事情。 因此,在按钮上,我使用代码登录然后发布,因为如果已经登录,则会跳过登录。 我遇到的问题是在登录代码之后立即运行邮政编码,因此在用户有机会登录之前。这将导致 2 个弹出窗口被打开(1 个登录和 1 个显示登录为尚未登录的帖子)。

如何让我的代码等待用户登录,然后再转到代码中的下一行发布?

FacebookHelper.h

@interface FacebookHelper : NSObject <FBSessionDelegate, FBRequestDelegate, FBDialogDelegate, FBLoginDialogDelegate> 
    Facebook *_facebook;
    NSArray *_permissions;


@property (nonatomic,strong) Facebook *facebook;

+(FacebookHelper *) sharedInstance;
+(void)fbDidLogin;

#pragma mark - Public Methods
-(BOOL) isFBSessionValid;
-(void) login;
-(void) logout;
-(void) postToWallWithDialogNewHighscore:(int)highscore;

@end

FacebookHelper.m

@implementation FacebookHelper
@synthesize facebook;

#pragma mark -
#pragma mark Singleton Variables
static FacebookHelper *singletonDelegate = nil;

#pragma mark -
#pragma mark Singleton Methods

+(FacebookHelper *)sharedInstance

    @synchronized(self) 
        if (singletonDelegate == nil) 
            singletonDelegate = [[self alloc] init]; // Assignment not done here
        
    
    return singletonDelegate;


-(id)init

    self = [super init];
    if (self) 
        _facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
        // Restore previous session
        NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
        if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) 
        _facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        _facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
        
        //
    
    return self;


+(id)allocWithZone:(NSZone *)zone

    @synchronized(self) 
        if (singletonDelegate == nil) 
            singletonDelegate = [super allocWithZone:zone];
            // assignment and return on first allocation
            return singletonDelegate;
        
    
    //on subsequent allocation attemps, return nil
    return nil;


-(id)copyWithZone:(NSZone *)zone

    return self;


#pragma mark - Facebook Delegate Methods

-(void)fbDidLogin

    NSLog(@"fbDidLogin");
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[_facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[_facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];


-(void)fbDidLogout

    NSLog(@"fbDidLogout");
    // Remove saved authorisation information if it exists
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:@"FBAccessTokenKey"]) 
        [defaults removeObjectForKey:@"FBAccessTokenKey"];
        [defaults removeObjectForKey:@"FBExpirationDateKey"];
        [defaults synchronize];
    


#pragma mark - Public Methods

-(NSMutableDictionary *) buildPostParamsWithHighScore:(int)highscore

    NSString *customMessage = [NSString stringWithFormat:kCustomMessage, highscore, kAppName];
    NSString *postName = kAppName;
    NSString *serverLink = [NSString stringWithFormat:kServerLink];
    NSString *imageSrc = kImageScr;

    //Final params build
    NSMutableDictionary *params = [NSMutableDictionary dictionaryWithObjectsAndKeys:
                                   //@"message", @"message",
                                   imageSrc, @"picture",
                                   serverLink, @"link",
                                   postName, @"name",
                                   @" ", @"caption",
                                   customMessage, @"description",
                                   nil];
    return params;


-(BOOL) isFBSessionValid

    // Check if there is a valid session
    //_facebook = [[Facebook alloc] initWithAppId:kAppId andDelegate:self];
    _facebook.accessToken = [[NSUserDefaults standardUserDefaults] objectForKey:@"FBAccessTokenKey"];
    _facebook.expirationDate = [[NSUserDefaults standardUserDefaults] objectForKey:@"FBExpirationDateKey"];
    NSLog(@"accessToken=%@ expirationDaate=%@",_facebook.accessToken,_facebook.expirationDate);
    if (![_facebook isSessionValid]) 
        NSLog(@"FacebookHelper isFBSessionValid = NO");
        return NO;
     else 
        NSLog(@"FacebookHelper isFBSessionValid = YES");
        return YES;
    

    return NO;


-(void) login

    NSLog(@"FacebookHelper login");
    _permissions = [NSArray arrayWithObjects:@"publish_stream", nil]; //@"read_stream", @"offline_access"
    [_facebook authorize:_permissions];


-(void) logout

    [_facebook logout];


-(void) postToWallWithDialogNewHighscore:(int)highscore

    NSMutableDictionary *params = [self buildPostParamsWithHighScore:highscore];

    NSLog(@"Post Feed");
    [_facebook dialog:@"feed" andParams:params andDelegate:self];


@end

按钮操作:

- (IBAction)facebookTest:(id)sender 
    [[FacebookHelper sharedInstance] login];
    [[FacebookHelper sharedInstance] postToWallWithDialogNewHighscore:123];

【问题讨论】:

【参考方案1】:

我已更新单例类以将分数发布到 Facebook Wall。查看新版本:http://indiedevstories.com/2012/04/11/facebookscorer-post-highscores-to-users-facebook-wall/

这个新版本在需要授权和登录时正确处理内部状态。

HTH

【讨论】:

【参考方案2】:

您需要做的是让您的 postToWallWithDialogNewHighscore 调用登录(如有必要),然后等待 FBSession 委托的回复。然后您需要设置您的 facebook fbDidLogin 委托,以便在完成后发送回一条消息。有很多方法可以做到这一点(登录后选择器、NSNotificationCenter 等)。像这样的东西应该可以工作(注意,为了方便起见,我假设 NSMutableDictionary *postParams 的 ivar):

-(void)doPost 
    NSLog(@"Post Feed");
    [_facebook dialog:@"feed" andParams:postParams andDelegate:self];


-(void)postToWallWithDialogNewHighscore:(int)highscore

    postParams = [self buildPostParamsWithHighScore:highscore];
    if (_facebook.isSessionValid) 
        [self doPost];
     else 
        //register an observer for FB login messages
        [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(postToWallObserver:) name:@"FBLoginComplete" object:nil];
        [self login];
    


-(void)fbDidLogin 
    NSLog(@"token granted until %@", [_facebook expirationDate]);
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[_facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[_facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"FBLoginComplete" object:nil];    


-(void)fbDidNotLogin:(BOOL)cancelled 
    //do nothing as they didn't login   


-(void) postToWallObserver:(NSNotification *) notification 
    if ([[notification name] isEqualToString:@"FBLoginComplete"]) 
        if ([_facebook isSessionValid]) 
            [self doPost];
         
    
    [[NSNotificationCenter defaultCenter] removeObserver:self];       

注意:这段代码我没有编译,所以可能有错别字等。

【讨论】:

顺便说一句,您不需要在界面中包含 FBLoginDialogDelegate 协议。

以上是关于发布前xcode自动登录中的Facebook SDK Singleton?的主要内容,如果未能解决你的问题,请参考以下文章

Xcode 9 没有这样的模块“Facebook 登录”

Facebook 和 Google 登录 - 冲突 (Xcode)

xcode 项目总是获得 facebook 登录失败状态

Facebook 登录错误 - Xcode 8 GM

如何在 Xcode 上舍入 Facebook 登录 UIImageView 角

IOS 9.2 Xcode 7.2 Facebook 登录问题