Как правильно использовать API-интерфейс Facebook для iOS

69
11

Я создаю приложение, где мне нужно вызывать запросы в нескольких контроллерах представлений. Я не хочу, чтобы экран входа в систему 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. Я действительно надеюсь, что кто-то столкнулся с этой проблемой раньше. Я хочу делать запросы в разных местах моего кода, но только тогда, когда пользователь вошел в систему, и ему нужно WAIT, пока пользователь входит в систему перед запросом. Код ниже не работает, но он показывает, что я хочу!


- (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;
}

спросил(а) 2011-08-29T23:01:00+04:00 8 лет, 10 месяцев назад
1
Решение
65

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

- (void)viewDidLoad {
[super viewDidLoad];

Facebook *facebook = [PBSocialMedia sharedFacebook];

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

ответил(а) 2011-08-30T02:40:00+04:00 8 лет, 10 месяцев назад
Ваш ответ
Введите минимум 50 символов
Чтобы , пожалуйста,
Выберите тему жалобы:

Другая проблема