Как правильно использовать Facebook Graph API на iOS - PullRequest
2 голосов
/ 30 августа 2011

Я делаю приложение, где мне нужно вызывать запросы в нескольких контроллерах представления.Я не хочу, чтобы экран входа в Facebook отображался при запуске приложения.Он должен открываться только тогда, когда пользователь нажимает кнопку в другом контроллере представления, если пользователь не вошел в систему, поэтому помещение кода в делегат приложения не является эффективным решением проблемы.И весь асинхронный процесс запроса данных в API Facebook убивает меня, я начинаю терять голову.

Класс со статическими методами для получения объекта facebook и обработки его как одиночного.

#import "PBSocialMedia.h"
#import "PBFacebookDelegate.h"

static Facebook *facebook;
static PBFacebookDelegate *facebookDelegate;

@implementation PBSocialMedia

+ (Facebook *)sharedFacebook {

    if (facebook == nil) {
        facebookDelegate = [[PBFacebookDelegate alloc] init];
        facebook = [[Facebook alloc] initWithAppId:@"156687441079334" andDelegate:facebookDelegate];
    }

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:@"FBAccessTokenKey"] 
        && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
    }

    NSArray *permissions = [NSArray arrayWithObjects:@"user_photo_video_tags", @"friends_photo_video_tags", @"user_photos", @"friends_photos", nil];

    if (![facebook isSessionValid]) {
        [facebook authorize:permissions];
    } else {
        [[NSNotificationCenter defaultCenter] postNotificationName:@"connectedToFacebook" object:self];
    }

    return facebook;
}

+ (Facebook *)sharedFacebookWithoutAuthorizing {
    return facebook;
}

@end

Класс, который реализует используемый делегат сеанса Facebookв классе выше

#import "PBFacebookDelegate.h"
#import "PBSocialMedia.h"

@implementation PBFacebookDelegate

/**
 * Called when the user successfully logged in.
 */
- (void)fbDidLogin {
    Facebook *facebook = [PBSocialMedia sharedFacebook];

    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];

    [[NSNotificationCenter defaultCenter] postNotificationName:@"connectedToFacebook" object:self];
}

/**
 * Called when the user dismissed the dialog without logging in.
 */
- (void)fbDidNotLogin:(BOOL)cancelled {
    [[NSNotificationCenter defaultCenter] postNotificationName:@"dismissedFacebookDialog" object:self];
}

/**
 * Called when the user logged out.
 */
- (void)fbDidLogout {
   [[NSNotificationCenter defaultCenter] postNotificationName:@"disconnectedFromFacebook" object:self];
}


@end

Как вы видите из двух классов выше, я использую уведомления, чтобы я знал, когда пользователь входит / выходит из Facebook.Приведенный ниже код является примером того, как я пытаюсь его использовать:

- (void)viewDidLoad {
    [super viewDidLoad];

    Facebook *facebook = [PBSocialMedia sharedFacebook];

    if (self.canUseGraphAPI) {
        [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self];
        NSLog(@"Can use");
    } else {
        NSLog(@"Can't use");
    }
}

- (void)connectedToFacebook {
    self.canUseGraphAPI = YES;
}

- (void)disconnectedFromFacebook {
    self.canUseGraphAPI = NO;
}

Конечно, это НЕ работает, как задумано из-за глупого асинхронного запроса.Он будет работать корректно только тогда, когда пользователь вошел в систему. Поэтому, когда я в первый раз открываю приложение, оно вызывает [PBSocialMedia sharedFacebook]; Затем оно выполняет функцию запроса И НЕ ожидает завершения функции sharedFacebook.Я действительно надеюсь, что кто-то сталкивался с этой проблемой раньше.Я хочу делать запросы в разных местах в моем коде, но только когда пользователь вошел в систему, и он должен ждать, пока пользователь входит в систему, прежде чем запрашивать.Код ниже не работает, но он показывает, что я хочу!

- (void)viewDidLoad {
    [super viewDidLoad];

    Facebook *facebook = [PBSocialMedia sharedFacebook];

    while (self.canUseGraphAPI) {
        // WAITING FOR LOGIN IN
    }

    [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self];
}

- (void)connectedToFacebook {
    self.canUseGraphAPI = YES;
}

- (void)disconnectedFromFacebook {
    self.canUseGraphAPI = NO;
}

1 Ответ

2 голосов
/ 30 августа 2011

Я бы начал реструктурировать ваш код для работы, передав блоки, которые вы хотите выполнить после получения ответа от FB. Это похоже на то, как вы делаете AJAX в JQuery.

- (void)viewDidLoad {
[super viewDidLoad];

Facebook *facebook = [PBSocialMedia sharedFacebook];

[self withGraphAPIDo: ^{
    [facebook requestWithGraphPath:@"106378916135129/photos" andDelegate:self];
    }];
}
...