2013-06-20 4 views
1

Я создаю приложение с навигационной панелью в навигационной панели.Facebook ios sdk login from UINavigationBar

Я пытаюсь понять, как использовать facebook sdk для подключения к facebook (аутентификация) при нажатии кнопки.

Это не какой-то специальный диспетчер представлений или что-то в этом роде.

Я видел это: http://developers.facebook.com/docs/tutorials/ios-sdk-tutorial/authenticate/

но там мне нужно, чтобы создать некоторые вещи в делегатом (как UINavigationController), что я не могу использовать, потому что я использую UITabBarController ..

как я могу реализовать логин facebook и создание сеанса только от нажатия UINavigationItem?

Вот мой AppDelegate.h:

#import <UIKit/UIKit.h> 
#import <FacebookSDK/FacebookSDK.h> 

@interface AppDelegate : UIResponder <UIApplicationDelegate> 

@property (strong, nonatomic) UIWindow *window; 
@property (strong, nonatomic) UITabBarController *tbc; 

@property (strong, nonatomic) FBSession *session; 


@end 

И мой AppDelegate.m:

#import "AppDelegate.h" 
#import "StatusView.h" 
#import "JokesView.h" 
#import "HomeView.h" 
#import "TopTenView.h" 
#import "UploadView.h" 

@implementation AppDelegate 

@synthesize tbc; 
@synthesize window = _window; 
@synthesize session = _session; 

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions 
{ 
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; 
    // Override point for customization after application launch. 
    self.window.backgroundColor = [UIColor whiteColor]; 

    UINavigationController*nav1 = [[UINavigationController alloc]init]; 
    UINavigationController*nav2 = [[UINavigationController alloc]init]; 
    UINavigationController*nav3 = [[UINavigationController alloc]init]; 
    UINavigationController*nav4 = [[UINavigationController alloc]init]; 
    UINavigationController*nav5 = [[UINavigationController alloc]init]; 

    StatusView*page1 = [[StatusView alloc]initWithNibName:@"StatusView" bundle:nil]; 
    JokesView*page2 = [[JokesView alloc]initWithNibName:@"JokesView" bundle:nil]; 
    HomeView*page3 = [[HomeView alloc]initWithNibName:@"HomeView" bundle:nil]; 
    TopTenView*page4 = [[TopTenView alloc]initWithNibName:@"TopTenView" bundle:nil]; 
    UploadView*page5 = [[UploadView alloc]initWithNibName:@"UploadView" bundle:nil]; 

    page1.title = @"סטטוסים"; 
    page2.title = @"תמונות"; 
    page3.title = @"ראשי"; 
    page4.title = @"Top 10"; 
    page5.title = @"העלאה"; 

    UITabBarItem *tab1 = [[UITabBarItem alloc] initWithTitle:@"Status" 
                 image:[UIImage imageNamed:@"tbc-status.png"] tag:1]; 
    [nav1 setTabBarItem:tab1]; 

    UITabBarItem *tab2 = [[UITabBarItem alloc] initWithTitle:@"Jokes" 
                 image:[UIImage imageNamed:@"tbc-jokes.png"] tag:1]; 
    [nav2 setTabBarItem:tab2]; 

    UITabBarItem *tab3 = [[UITabBarItem alloc] initWithTitle:@"Home" 
                 image:[UIImage imageNamed:@"tbc-home.png"] tag:1]; 
    [nav3 setTabBarItem:tab3]; 

    UITabBarItem *tab4 = [[UITabBarItem alloc] initWithTitle:@"Tpp10" 
                 image:[UIImage imageNamed:@"tbc-topten.png"] tag:1]; 
    [nav4 setTabBarItem:tab4]; 

    UITabBarItem *tab5 = [[UITabBarItem alloc] initWithTitle:@"Upload" 
                 image:[UIImage imageNamed:@"tbc-upload.png"] tag:1]; 
    [nav5 setTabBarItem:tab5]; 


    [nav1 pushViewController:page1 animated:NO]; 
    [nav2 pushViewController:page2 animated:NO]; 
    [nav3 pushViewController:page3 animated:NO]; 
    [nav4 pushViewController:page4 animated:NO]; 
    [nav5 pushViewController:page5 animated:NO]; 

    tbc = [[UITabBarController alloc]init]; 
    tbc.viewControllers = [NSArray arrayWithObjects:nav5,nav4,nav3,nav2,nav1, nil]; 
    tbc.selectedIndex = 2; 

    // NavBar Design 
    UIImage *navbarPortrait = [[UIImage imageNamed:@"topbar.jpg"] 
           resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; 
    UIImage *navbarLandscape = [[UIImage imageNamed:@"topbar.jpg"] 
           resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; 

    [[UINavigationBar appearance] setBackgroundImage:navbarPortrait 
             forBarMetrics:UIBarMetricsDefault]; 
    [[UINavigationBar appearance] setBackgroundImage:navbarLandscape 
             forBarMetrics:UIBarMetricsLandscapePhone]; 
    // NavBar Design End 

    // TabBar Design 
    UIImage *tabBackground = [[UIImage imageNamed:@"tbcb3ack.png"] 
           resizableImageWithCapInsets:UIEdgeInsetsMake(0, 0, 0, 0)]; 
    [[UITabBar appearance] setBackgroundImage:tabBackground]; 
    [[tbc tabBar] setBackgroundImage:tabBackground]; 
    // TabBar Design End 

    [self.window addSubview:tbc.view]; 
    self.window.rootViewController = self.tbc; 

    // Push Notifications 
    [[UIApplication sharedApplication] registerForRemoteNotificationTypes:(UIRemoteNotificationTypeAlert | UIRemoteNotificationTypeBadge | UIRemoteNotificationTypeNone)]; 
    // Push Notifications End 

    // Facebook Code Start 

    //UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Not Logged in" 
    //            message:@"You Log in to use all the fearues in this app" 
    //            delegate:nil 
    //          cancelButtonTitle:@"OK" 
    //          otherButtonTitles:nil]; 

    if (FBSession.activeSession.state == FBSessionStateCreatedTokenLoaded) { 
     // To-do, show logged in view 
    } else { 
     //[alert show]; 

    } 

    // Facebook Code End 

    [self.window makeKeyAndVisible]; 
    return YES; 

} 

// Facebook sdk code Start 

- (BOOL)application:(UIApplication *)application 
      openURL:(NSURL *)url 
    sourceApplication:(NSString *)sourceApplication 
     annotation:(id)annotation { 
    // attempt to extract a token from the url 
    return [FBAppCall handleOpenURL:url 
        sourceApplication:sourceApplication 
         withSession:self.session]; 
} 

// Facebook sdk code End 

- (void)applicationWillResignActive:(UIApplication *)application 
{ 
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state. 
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game. 
} 

- (void)applicationDidEnterBackground:(UIApplication *)application 
{ 
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later. 
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits. 
} 

- (void)applicationWillEnterForeground:(UIApplication *)application 
{ 
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background. 
} 

- (void)applicationDidBecomeActive:(UIApplication *)application 
{ 
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface. 
} 

- (void)applicationWillTerminate:(UIApplication *)application 
{ 
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:. 
     [FBAppCall handleDidBecomeActiveWithSession:self.session]; 
} 
#pragma mark Template generated code 

@end 

Это после того, как я использовал аутентификации учебник facebook Иос, до фактического фб изменения сеанса и кнопка входа в систему.

+0

Что вы пробовали? Можете ли вы опубликовать код? – laxonline

+0

Я пробовал только один и какой-то старый учебник ... У меня нет текущего кода, потому что он просто не работает, поскольку я пытаюсь не использовать логин в качестве полного контроллера представления, но как функцию anyviewcontroller у меня есть/ –

ответ

3

Решить эту проблему действительно две части. Сначала вам нужно определить UIButton как UINavigationItem, который будет делать ваш логин (или выйти) при нажатии. Во-вторых, ваше приложение должно быть готово принять событие входа. Я не уверен, какая часть причиняют вам больше хлопот, но вот как вы создали первую часть, кнопку:

UIButton *loginButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
loginButton.frame = CGRectMake(0.0f, 0.0f, 75.0f, 44.0f); 
[loginButton setTitle:@"Login" forState:UIControlStateNormal]; 
[loginButton addEventHandler:^(id sender) 
{ 
    [FBSession openActiveSessionWithReadPermissions:nil 
             allowLoginUI:YES 
            completionHandler: 
             ^(FBSession *session, 
             FBSessionState state, NSError *error) { 
        [self sessionStateChanged:session state:state error:error]; 
    }]; 
} 
forControlEvents:UIControlEventTouchUpInside]; 
[self.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:loginButton]; 

Что касается второй части, то необходимо определить функцию sessionStateChanged в этой точке зрения контроллера. Чтобы сохранить вам неприятности, вот общая структура, что вам нужно для метода sessionStateChanged:

- (void)sessionStateChanged:(FBSession *)session 
         state:(FBSessionState) state 
         error:(NSError *)error 
{ 
    switch (state) { 
     case FBSessionStateOpen: 
      // Connected to facebook... so go to your next view controller 
      break; 
     case FBSessionStateClosed: 
     case FBSessionStateClosedLoginFailed: 
      // Login failed 
      [FBSession.activeSession closeAndClearTokenInformation]; 
      break; 
     default: 
      break; 
    } 

    if (error) { 
     UIAlertView *alertView = [[UIAlertView alloc] 
        initWithTitle:@"Error" 
          message:error.localizedDescription 
          delegate:nil 
       cancelButtonTitle:@"OK" 
       otherButtonTitles:nil]; 
     [alertView show]; 
    }  
} 

Вам также необходимо осуществить много других вещей, особенно в делегат своего приложения. Я счастлив выписать больше образцов кода для вас, но помогите мне понять, что вы хотите увидеть дальше.

UPDATE

Итак, теперь, когда я понимаю, что вы хотите, чтобы эта кнопка facebook остаться с вами на панели навигации, я бы подклассы контроллера нав, установите subclasss быть своим собственным делегатом, и добавить facebook кнопка для каждого добавленного контроллера. Следует отметить, что нарисованная навигационная панель использует элемент navigationItem каждого контроллера вида, который добавлен в контроллер навигации. Так что технически вам нужно добавить эту же кнопку на каждый контроллер вида, который вытолкнут или выскочил из навигационного контроллера.Вместо того, чтобы скопировать код или даже создать класс утилиты (или суперкласс), который все ваши контроллеры представлений используют для вставки этой кнопки facebook, быстрый и грязный способ заключается в создании одной кнопки в подклассе контроллера навигации и вставка этого отображается одна и та же кнопка, как и каждый контроллер вида. Так вот очень голые кости версия о том, что навигационный контроллер подкласс может выглядеть в его файле реализации:

@interface MYNavigationController() <UINavigationControllerDelegate> 
@property (nonatomic, strong)   UIButton *facebookButton; 
@end 

@implementation MYNavigationController 

- (void)viewDidLoad 
{ 
    [super viewDidLoad]; 

    // Set this subclass as its own delegate to be able receive the willShowViewController: method 
    self.delegate      = self; 

    // Create a shared facebook button 
    _facebookButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
    _facebookButton.frame = CGRectMake(0.0f, 0.0f, 75.0f, 44.0f); 
    [_facebookButton setTitle:@"Login" forState:UIControlStateNormal]; 
    [_facebookButton 
     addTarget:self 
     action:@selector(onFacebookButtonClick:) 
     forControlEvents:UIControlEventTouchUpInside]; 
} 

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    // As each view controller is about to be shown, change the view controller's 
    // navigationItem to have this facebook button as its right bar button 
    viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.facebookButton]; 
} 

- (void)onFacebookButtonClick:(id)sender 
{ 
    // Handle the click event when the facebook button is clicked 
    // You need to have logic here to know if the session is open or not 
    // Of course, when the session isn't open, then open a new session (ie. login) 
    // and when the session IS open, then close the session (ie. logout) 
    [FBSession 
     openActiveSessionWithReadPermissions:nil 
     allowLoginUI:YES 
     completionHandler: ^(FBSession *session, FBSessionState state, NSError *error) 
     { 
      [self sessionStateChanged:session state:state error:error]; 
     }]; 
} 

- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error 
{ 
    switch (state) { 
     case FBSessionStateOpen: 
      // Connected to facebook so... 
      // 1. change the button text to say "logout" instead of "login" 
      // 2. go to your next view controller 
      break; 
     case FBSessionStateClosed: 
     case FBSessionStateClosedLoginFailed: 
      // Login failed so revert everything to pre-login state 
      [FBSession.activeSession closeAndClearTokenInformation]; 
      break; 
     default: 
      break; 
    } 

    if (error) { 
     UIAlertView *alertView = [[UIAlertView alloc] 
            initWithTitle:@"Error" 
            message:error.localizedDescription 
            delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil]; 
     [alertView show]; 
    } 
} 

А потом, просто использовать этот MYNavigationController как ваш класс навигации контроллера. Не забудьте пройти facebook ios authentication tutorial, чтобы узнать, как настроить приложение (есть множество фреймворков для добавления, инфо-список и т. Д.).

Счастливые, чтобы помочь больше, если вам это нужно!

Update # 2

Поскольку контроллер представления корня вашего окна является UITabBarController, то мы можем использовать его в качестве владельца facebookButton, который распределяется между всеми UINavigationControllers. На высоком уровне логика не изменилась с моей предыдущей выборки кода. Вы создаете одну кнопку где-то, это добавляется к каждому контроллеру представления, который отображается вашими навигационными контроллерами. Для этого вам нужно сначала создать подкласс UITabBarController (опять же, мой называется MYTabBarController, но вы можете назвать его, как хотите). И это будет выглядеть примерно так, как это в MYTabBarController.m:

#import "MYTabBarController.h" 
#import <FacebookSDK/FacebookSDK.h> 

@implementation MYTabBarController 

- (UIButton *)facebookButton 
{ 
    if (! _facebookButton) 
    { 
     // Create a shared facebook button on demand 
     _facebookButton = [UIButton buttonWithType:UIButtonTypeCustom]; 
     _facebookButton.frame = CGRectMake(0.0f, 0.0f, 75.0f, 44.0f); 
     [_facebookButton setTitle:@"Login" forState:UIControlStateNormal]; 
     [_facebookButton 
      addTarget:self 
      action:@selector(onFacebookButtonClick:) 
      forControlEvents:UIControlEventTouchUpInside]; 
    } 
    return _facebookButton; 
} 

- (void)navigationController:(UINavigationController *)navigationController willShowViewController:(UIViewController *)viewController animated:(BOOL)animated 
{ 
    // As each view controller is about to be shown, change the view controller's 
    // navigationItem to have this facebook button as its right bar button 
    viewController.navigationItem.rightBarButtonItem = [[UIBarButtonItem alloc] initWithCustomView:self.facebookButton]; 
} 

- (void)onFacebookButtonClick:(id)sender 
{ 
    // Handle the click event when the facebook button is clicked 
    // You need to have logic here to know if the session is open or not 
    // Of course, when the session isn't open, then open a new session (ie. login) 
    // and when the session IS open, then close the session (ie. logout) 
    [FBSession 
     openActiveSessionWithReadPermissions:nil 
     allowLoginUI:YES 
     completionHandler: ^(FBSession *session, FBSessionState state, NSError *error) 
     { 
      [self sessionStateChanged:session state:state error:error]; 
     }]; 
} 

- (void)sessionStateChanged:(FBSession *)session state:(FBSessionState)state error:(NSError *)error 
{ 
    switch (state) { 
     case FBSessionStateOpen: 
      // Connected to facebook so... 
      // 1. change the button text to say "logout" instead of "login" 
      //  eg. [self.facebookButton setTitle:@"Logout" forState:UIControlStateNormal]; 
      // 2. go to your next view controller 
      break; 
     case FBSessionStateClosed: 
     case FBSessionStateClosedLoginFailed: 
      // Login failed so revert everything to pre-login state 
      [FBSession.activeSession closeAndClearTokenInformation]; 
      break; 
     default: 
      break; 
    } 

    if (error) { 
     UIAlertView *alertView = [[UIAlertView alloc] 
            initWithTitle:@"Error" 
            message:error.localizedDescription 
            delegate:nil 
            cancelButtonTitle:@"OK" 
            otherButtonTitles:nil]; 
     [alertView show]; 
    } 
} 

Соответствующее MYTabBarController.h нужно будет иметь по крайней мере, кнопка, определенный и тот факт, что соответствует в UINavigationControllerDelegate протокола:

@interface MYTabBarController: UITabBarController<UINavigationControllerDelegate> 

@property (nonatomic, strong)   UIButton *facebookButton; 

Наконец, ваше приложение делегату application:didFinishLaunchingWithOptions: необходимо внести небольшие изменения. Он должен объявить панель вкладок в качестве делегата для каждого из ваших UINavigationControllers:

// Set the navigation controller delegates to be the tabbar in order to hook into the willShowViewController: method 
nav1.delegate      = tbc; 
nav2.delegate      = tbc; 
nav3.delegate      = tbc; 
nav4.delegate      = tbc; 
nav5.delegate      = tbc; 

Это должно сделать это. Надеюсь, вы можете взять это отсюда. Удачи!

+0

спасибо за замечательный комментарий! какие файлы мне нужно импортировать для этого? и мне нужна функция сеанса на каждой странице? Я не приму приложение, чтобы помнить, что пользовательский trhow все его страницы. спасибо :) –

+0

Ahh, я начинаю видеть, что вам нужно. Таким образом, вы действительно хотите, чтобы кнопка входа/выхода осталась с контроллером навигации, независимо от того, какой контроллер просмотра отображается правильно? Если это так, то вам нужно подклассифицировать UINavigationController, добавить это как часть вашего подкласса и обработать всю логику facebook в навигационном контроллере. Если это так, просто скажите мне, и я могу отредактировать свой ответ, чтобы быть более конкретным. –

+0

да это он! я буду рад, если вы сможете показать мне, как это сделать :) –

0

Когда вы нажимаете на viewController, вам следует назначать viewControler раньше. И вы можете реализовать логин facebook и создание сеанса в функции alloc из viewController.

+0

i не хотят внедряться в новый диспетчер представлений, но использовать как функцию в exsiting ... возможно? –

0

Это возможно. Вы можете создать логин и сеанс facebook в appDelegate. Когда вам нужно показать просмотр на facebook, вы можете вызвать функцию для всплывающего просмотра в facebook.

+0

Можете ли вы дать мне пример кода? и я не хочу всплывающего окна, я хочу, чтобы он перешел в приложение facebook для проверки и вернулся. –