4

Facebook を iOS アプリに統合する際に問題が発生しています。アプリを起動すると、Facebook アプリにリダイレクトされます。しかし、認証ダイアログは画面から消えるだけで (モーダル ビュー コントローラーが閉じられたように)、デリゲート メソッドは起動せず、アプリにリダイレクトされるのではなく、Facebook アプリに残されます。セッションを正常に初期化していないようです。iOS チュートリアルの手順に従いましたが、どこかで間違っているに違いありません。私が見た質問のほとんどは、エラーに関するものか、認証ダイアログから別の動作を取得しようとするものでした。これがだまされている場合は、ここで壁にぶつかっているので、同じ質問に誘導してください。チュートリアルで説明されているように、.plist をセットアップしました。iTunes Connect から取得したアプリのバンドル ID を使用しました。私の定数 kAppID は、Facebook 開発者アプリ インターフェイスから取得した AppID です。FB 静的ライブラリのヘッダーと実装ファイル、および FB のドキュメントとチュートリアルを読んだ後、FB アプリにリダイレクトしてサインインし、自分のアプリにリダイレクトされることだけが必要な場合は、そう思われます。 、これらの手順と以下のコードで十分であることを確認してください。

AppDelegate.m で:

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    kAppID = @"(this is where my app ID is)";
    // Override point for customization after application launch.
    facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:self];
    [facebook setSessionDelegate:self];
    return YES;
}

ViewController.m で、Facebook の同じインスタンスへの参照を取得し、次のように呼び出します。

- (void)loginToFacebook:(id)sender {
    if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
    }
    if (![facebook isSessionValid]) {
        [facebook authorize:nil];
    }
}

私が気付いていない落とし穴はありますか?それとも、重要なステップを見逃しているのでしょうか?

ところで、Xcode 4.3.1、ios5SDK、iPhone 4S、ARC.

.plist の SS。ここに画像の説明を入力

AppDelegate.h:

#import <UIKit/UIKit.h>
#import "Facebook.h"
#import "FBConnect.h"

@interface AppDelegate : UIResponder <UIApplicationDelegate> {
    Facebook *facebook;
    NSUserDefaults *defaults;
    NSString *kAppID;
}

@property (strong, nonatomic) UIWindow *window;
@property (strong, nonatomic) Facebook *facebook;
@property (strong, nonatomic) id delegate;

@end

AppDelegate.m:

#import "AppDelegate.h"
#import "ViewController.h"

@implementation AppDelegate

@synthesize window = _window;
@synthesize facebook;
@synthesize delegate;

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    ViewController *viewController = [[ViewController alloc] init];
    kAppID = @"385380598149062";
    facebook = [[Facebook alloc] initWithAppId:kAppID andDelegate:viewController];

    return YES;
}

- (void)showSession {
    NSLog(@"FB Session: %@", [NSNumber numberWithBool:[facebook isSessionValid]]);
}

@end

ご覧のとおり、これらのメソッドではあまり起こりません。デリゲート クラスは ViewController です。AppDelegate で実際に行うことは、Facebook インスタンスを初期化することだけです。その点については、ViewController.m 全体を以下に示します (Facebook に関連しないものを除く):

#import "ViewController.h"

@interface ViewController ()

@end

@implementation ViewController

@synthesize contacts, contactArray;

- (void)viewDidLoad
{
    [super viewDidLoad];
    defaults = [NSUserDefaults standardUserDefaults];
    AppDelegate *delegate = (AppDelegate *)[[UIApplication sharedApplication] delegate];
    facebook = delegate.facebook;
    [facebook setSessionDelegate:self];
    [self loginToFacebook:nil];
    eventsArray = [[NSMutableArray alloc] initWithObjects:@"Event one", @"Event two", nil];
}

- (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
{
    if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPhone) {
        return (interfaceOrientation = UIInterfaceOrientationPortrait);
    } else {
        return NO;
    }
}

- (void)loginToFacebook:(id)sender {
    if ([defaults objectForKey:@"FBAccessTokenKey"] && [defaults objectForKey:@"FBExpirationDateKey"]) {
        facebook.accessToken = [defaults objectForKey:@"FBAccessTokenKey"];
        facebook.expirationDate = [defaults objectForKey:@"FBExpirationDateKey"];
        NSLog(@"accessToken:%@\n expiry:%@", facebook.accessToken, facebook.expirationDate);
    }
    if (![facebook isSessionValid]) {
        [facebook authorize:nil];
    }
}

- (BOOL)application:(UIApplication *)application handleOpenURL:(NSURL *)url {
    NSLog(@"handle open url");
    return [facebook handleOpenURL:url];
}

- (BOOL)application:(UIApplication *)application openURL:(NSURL *)url sourceApplication:(NSString *)sourceApplication annotation:(id)annotation {
    return [facebook handleOpenURL:url];
}

- (void)request:(FBRequest *)request didLoad:(id)result {
    //ok so it's a dictionary with one element (key="data"), which is an array of dictionaries, each with "name" and "id" keys
    fbContacts = [(NSDictionary *)result objectForKey:@"data"];
    NSLog(@"Request did load");
    for (int i=0; i<[fbContacts count]; i++) {
        NSDictionary *friend = [fbContacts objectAtIndex:i];
        long long fbid = [[friend objectForKey:@"id"]longLongValue];
        NSString *name = [friend objectForKey:@"name"];
        NSLog(@"id: %lld - Name: %@", fbid, name);
    }
}

- (void)fbDidLogin {
    NSLog(@"FB did log in");
    [defaults setObject:[facebook accessToken] forKey:@"FBAccessTokenKey"];
    [defaults setObject:[facebook expirationDate] forKey:@"FBExpirationDateKey"];
    [defaults synchronize];
    [facebook requestWithGraphPath:@"me/friends" andDelegate:self];
}

- (void)fbDidNotLogin:(BOOL)cancelled {
    NSLog(@"FB login cancelled");
}

/**
 * Called after the access token was extended. If your application has any
 * references to the previous access token (for example, if your application
 * stores the previous access token in persistent storage), your application
 * should overwrite the old access token with the new one in this method.
 * See extendAccessToken for more details.
 */
- (void)fbDidExtendToken:(NSString*)accessToken
               expiresAt:(NSDate*)expiresAt {
    NSLog(@"FB extended token");
}

/**
 * Called when the user logged out.
 */
- (void)fbDidLogout {
    NSLog(@"FB logged out");
    [defaults removeObjectForKey:@"FBAccessTokenKey"];
    [defaults removeObjectForKey:@"FBExpirationDateKey"];
    [defaults synchronize];
}

/**
 * Called when the current session has expired. This might happen when:
 *  - the access token expired
 *  - the app has been disabled
 *  - the user revoked the app's permissions
 *  - the user changed his or her password
 */
- (void)fbSessionInvalidated {
    NSLog(@"FB session invalidated");
}
@end
4

3 に答える 3

2

.plist は良さそうですが、openurl ハンドラを忘れてしまったのでしょうか?

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

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

更新:

  1. 実験として、これを試していただけますか (Hackbook の例から):

    // Now check that the URL scheme fb[app_id]://authorize is in the .plist and can
    // be opened, doing a simple check without local app id factored in here
    NSString *url = [NSString stringWithFormat:@"fb%@://authorize",kAppId];
    BOOL bSchemeInPlist = NO; // find out if the sceme is in the plist file.
    NSArray* aBundleURLTypes = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleURLTypes"];
    if ([aBundleURLTypes isKindOfClass:[NSArray class]] &&
        ([aBundleURLTypes count] > 0)) {
        NSDictionary* aBundleURLTypes0 = [aBundleURLTypes objectAtIndex:0];
        if ([aBundleURLTypes0 isKindOfClass:[NSDictionary class]]) {
            NSArray* aBundleURLSchemes = [aBundleURLTypes0 objectForKey:@"CFBundleURLSchemes"];
            if ([aBundleURLSchemes isKindOfClass:[NSArray class]] &&
                ([aBundleURLSchemes count] > 0)) {
                NSString *scheme = [aBundleURLSchemes objectAtIndex:0];
                if ([scheme isKindOfClass:[NSString class]] &&
                    [url hasPrefix:scheme]) {
                    bSchemeInPlist = YES;
                }
            }
        }
    }
    // Check if the authorization callback will work
    BOOL bCanOpenUrl = [[UIApplication sharedApplication] canOpenURL:[NSURL URLWithString: url]];
    if (!bSchemeInPlist || !bCanOpenUrl) {
        UIAlertView *alertView = [[UIAlertView alloc]
                                  initWithTitle:@"Setup Error"
                                  message:@"Invalid or missing URL scheme. You cannot run the app until you set up a valid URL scheme in your .plist."
                                  delegate:self
                                  cancelButtonTitle:@"OK"
                                  otherButtonTitles:nil,
                                  nil];
        [alertView show];
        [alertView release];
    }
    

    このステップで、URL スキームに問題がないことがわかります。

  2. [facebook authorize:nil]; を変更してみてください。with [facebook authorize:[[NSArray alloc] initWithObjects:@"read_friendlists", nil]]; そのため、SSO には少なくとも 1 つのアクセス許可を指定する必要があるかもしれません。

于 2012-04-05T22:28:05.530 に答える
2

私は同じ問題を抱えていました.Facebookアプリにリダイレクトされ、認証ダイアログがすぐに閉じられ、Facebookアプリに残りました.

問題は .plist にあり、URL スキームで appID 番号の前に fb を入力するのを忘れていました。

plist

デリゲート メソッドがまだ起動しない場合は、アプリケーションのデリゲートにすべての facebook ロジックを配置する必要があるためです。上記の aurav aka sparsh も有効にしました。

于 2012-07-21T15:40:49.633 に答える
0

長い間苦労した後、最終的にこの問題の解決策を見つけましたが、それは正しいとは言えませんが、アプリの魅力のように機能します:

developer.facebook.com にアクセスしてください

リストからアプリを選択します (URL スキームで使用しているアプリ)

アプリがネイティブ アプリとして選択されている場合、バンドル ID が求められます

アプリを構築するために使用するバンドル識別子を彼に提供します

ワイルドカード バンドル識別子を使用している場合は、com.product.abc のように指定します。それ以外の場合は、完全なバンドル識別子を指定します。

FB ログインが機能し始めます。あなたの設定は、画像に示すようにする必要があります

于 2012-07-10T11:31:13.117 に答える