Facebook FBConnect SDK выдает на iOS - PullRequest
       25

Facebook FBConnect SDK выдает на iOS

8 голосов
/ 17 августа 2011

Я использую FBConnect SDK для публикации сообщений в профиле пользователя через мое приложение. У меня есть ряд проблем с этим:

Когда соответствующий код запускается на устройстве в первый раз, пользователь перенаправляется по желанию на приложение / веб-сайт Facebook, который просит его авторизовать его. если пользователь авторизует его, он возвращается обратно в приложение, которое открывает контроллер представления «Connect to facebook», который просит пользователя войти в систему. Это странно, поскольку пользователь уже вошел в систему, иначе как он мог авторизовать приложение ? но я думаю, что это может быть хорошо, так как он еще не вошел через приложение. после того, как он входит в систему, он ничего не делает. только во второй раз код запускается, после того как он авторизовал приложение, пользователь получает диалог публикации.

Если пользователь не авторизовал приложение, когда оно возвращается в мое приложение после диалога авторизации, он просит пользователя войти в систему (как если бы он авторизовался) и ничего не делает после того, как он вошел в систему. Только во второй раз код запускается, открывается диалоговое окно авторизации с опциями «Авторизовать» и «Выйти из приложения» вместо «Авторизовать» и «Не авторизовать» / «Разрешить» и «Не разрешать».

Кроме того, если пользователь удалил свою авторизацию через настройки своей учетной записи на Facebook, вместо того, чтобы просто попросить его повторно авторизовать его, появится диалоговое окно facebook (вместо диалога публикации / авторизации), говорящее: «Ошибка произошло. Пожалуйста, попробуйте позже. " Попытка позже не поможет. он будет появляться всегда, даже если вы перезапустите приложение. Единственный способ сделать это - переустановить приложение, после чего оно снова откроет диалоговое окно авторизации.

Вот чего я хочу достичь:

  1. После того, как пользователь авторизует приложение, ему больше не нужно будет входить в систему.
  2. После того, как пользователь авторизует приложение, диалоговое окно публикации появится сразу, без необходимости повторного запуска кода (который запускается, между прочим, с помощью кнопки).
  3. Если пользователь отменяет авторизацию приложения, ему снова будет предложено диалоговое окно авторизации вместо диалогового окна ошибки
  4. Если он отказался от авторизации, я вызову функцию, которая отображает ошибку / и т. Д.

Вот соответствующий код:

MyViewController.m

- (void)shareOnFacebook
{
    Facebook *facebook = [[Facebook alloc] initWithAppId:myAppID];
    [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] setFacebook:facebook];
    [facebook release];
    facebook = [(MyAppDelegate *)[[UIApplication sharedApplication] delegate] facebook];
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
    }
    if (![facebook isSessionValid]) {
        [facebook authorize:[NSArray arrayWithObjects:@"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
    }

     NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
     //Giving the dictionary some parameters for posting defaults
     [facebook dialog:@"feed" andParams:dictionary andDelegate:self]; //Note: we have 2 different delegates! appDelegate for connections & url switching, and self for dialogs
}

MyAppDelegate.h

@interface MyAppDelegate : NSObject <UIApplicationDelegate, FBSessionDelegate, FBDialogDelegate>
{  
    Facebook *facebook; // kept for facebook sharing, accessed only from MyViewController although delegate methods are handeled in here
}
@property (nonatomic, retain) Facebook *facebook;

@end

MyAppDelegate.m

- (void)fbDidLogin
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url
{
    return [self.facebook handleOpenURL:url];
}

Возможно ли, что мне не хватает нескольких функций делегата в MyViewController? Потому что я вижу, по какой-то причине, я пометил его как реализующий протокол FBDialogDelegate, хотя он оттуда не реализует никаких функций.

Я был бы очень рад, если бы вы, ребята, помогли мне, потому что это очень расстраивает меня. Я не мог ничего найти об этом в Интернете, и я чувствую, что я тону здесь.

Tnx заранее!

Ответы [ 6 ]

8 голосов
/ 27 августа 2011

Первый:

[facebook authorize:[NSArray arrayWithObjects:@"publish_stream",@"offline_access",nil] delegate:self];

Клавиша offline_access сохранит ваш токен авторизации навсегда (или, точнее, до тех пор, пока пользователь вручную не деавторизует ваше приложение в настройках приложения в Facebook. настройки аккаунта). Кроме того, установите ваш активный VC в качестве делегата (подробнее об этом позже).

Во-вторых:

-(void)popUserShareFeed {
  NSMutableDictionary *dictionary = [NSMutableDictionary dictionary];
  //Giving the dictionary some parameters for posting defaults
  [facebook dialog:@"feed" andParams:dictionary andDelegate:self];
}

Вызовите этот метод (или подобный ему) в вашем -fbDidLogin методе делегата. Также вызовите его в вашем исходном методе, если сеанс был все еще действителен, т.е.

if (![facebook isSessionValid]) {
        [facebook authorize:[NSArray arrayWithObjects:@"publish_stream", nil] delegate:(MyAppDelegate *)[[UIApplication sharedApplication] delegate]];
} else {
  [self popUserShareFeed];
}

... и ваш новый fbDidLogin:

- (void)fbDidLogin
{
    NSUserDefaults *defaults = [NSUserDefaults standardUserDefaults];
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];
    [self popUserShareFeed];
}

(Примечание: вам нужно определить это в MyViewController.m и использовать его как FBSessionDelegate. Это будет функционально эквивалентно. Ваш AppDelegate не обязательно должен быть вашим FBSessionDelegate.

Третье:

Реализуйте метод -fbDidNotLogin:(BOOL)cancelled FBSessionDelegate, например:

-(void)fbDidNotLogin:(BOOL)cancelled {
   if (cancelled) {
      ... some alert about the user cancelling...
   } else {
      ... some alert about how it failed for some reason...
   }
}

В-четвертых, что касается ваших странных ошибок: A) SDK Facebook в целом невелики, и B) я бы установил токен авторизации и дату истечения срока действия для вашего объекта facebook, если

A) у вас еще нет одного экземпляра (т.е. это nil)

и

B) заданная вами дата expirationDate (то есть timeIntervalSinceNow [вызванный метод NSDate экземпляр) возвращает> 0).

3 голосов
/ 19 августа 2011

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

У Facebook самые плохие документы для разработчиков и поддержка разработчиков, я бы не стал задерживать дыхание в ожидании решения.

1 голос
/ 27 декабря 2011

У меня была похожая, но не та же проблема: сообщение «Произошла ошибка. Пожалуйста, попробуйте позже». показывался всегда.

Проблема была в неправильно настроенном идентификаторе приложения - он был предоставлен клиентом (поэтому я не уверен, что именно было не так); все работает правильно, так как я заменил его своим собственным идентификатором тестового приложения (из предыдущего приложения).

0 голосов
/ 17 ноября 2011

У меня была точно такая же проблема, и я использовал ответ Бена Мошера, описанный выше, но я также решил создать простой одноэлементный класс для объекта Facebook, чтобы в моем AppDelegate я мог правильно обрабатывать следующую функцию:

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {

    return [[[FBManager defaultManager] facebook] handleOpenURL:url];

    //return [facebook handleOpenURL:url]; 
}

Мой одноэлементный класс - и FBSessionDelegate, и FBDialogDelegate, поэтому он обрабатывает соответствующие методы.

Это позволяет мне предлагать пользователю входить в систему только тогда, когда он пытается что-то опубликовать, а не когда приложение запускается.

0 голосов
/ 27 августа 2011

Не прямое решение ваших проблем с кодом, но ...

Рассматривали ли вы использовать для этого библиотеку с открытым исходным кодом?ShareKit - отличный пример: http://getsharekit.com.Интеграция очень проста и делает все, что вам нужно.

0 голосов
/ 20 августа 2011

Я интегрировал FBConnect во многих приложениях, но никогда не сталкивался с такой критической проблемой.Итак, в вашем коде чего-то не хватает:

Если вы проверяете FBAccessTokenKey & FBExpirationDateKey, просто попробуйте использовать объект сеанса класса FBSession класса FBConnect.

Просто попробуйте использовать мой код с несколькими условиями:

session = [[FBSession sessionForApplication:@"key" secret:@"AppSecretKey" delegate:self] retain];
        [session resume];
        _posting = YES;

        // If we're not logged in, log in first...
        if (![session isConnected]) {
            loginDialog = nil;
            loginDialog = [[FBLoginDialog alloc] init]; 
            [loginDialog show]; 
        }
            // If we have a session and a name, post to the wall!
            else if (_facebookName != nil) {
                        [self postToWall]; // Over here posting dialog will appear , if user has already logged in or session is running.
                    }

        }
        else {
            [FBBtn setTitle:@"Login" forState:UIControlStateNormal]; // if you want to change the title of button
            [session logout];
        }

Кроме того, позаботьтесь об освобождении объекта сеанса только в методе dealloc, а не об освобождении его любым другим методом.

 - (void)dealloc {
        [super dealloc];
        [session release];
        session = nil;
    }

Надеюсь, что это решит вашу проблему.

...