Facebook iOS SDK 登录原生和 UIWebView 登录
Posted
技术标签:
【中文标题】Facebook iOS SDK 登录原生和 UIWebView 登录【英文标题】:Facebook iOS SDK login native and UIWebView login 【发布时间】:2013-07-25 23:30:36 【问题描述】:对于我正在开发的应用程序,我需要用户能够使用本机 SDK 登录 Facebook,但该应用程序还有一个单独的部分使用 web 视图中的 FB cmets 小部件。问题是用户使用本机 SDK 登录后,他们没有在 webview cmets 小部件中登录。有没有办法让用户使用本机 ios SDK 登录,然后在 UIWebView 中将它们登录到 Facebook。我尝试在用户登录后在 FBSession 类中使用 openAccessTokenFromData:completionHandler: 但无法使其正常工作,如下所示
- (void)didLogin
FBAccessTokenData *data = [FBAccessTokenData createTokenFromString:[FBSession activeSession].accessTokenData.accessToken
permissions:[FBSession activeSession].accessTokenData.permissions
expirationDate:[FBSession activeSession].accessTokenData.expirationDate
loginType:FBSessionLoginTypeWebView
refreshDate:nil];
[[FBSession activeSession] closeAndClearTokenInformation];
FBSession *session = [[FBSession alloc] init];
[session openFromAccessTokenData:data
completionHandler:^(FBSession *session, FBSessionState status, NSError *error)
];
【问题讨论】:
【参考方案1】:我使用以下代码在我的本机应用程序的 Webview 中打开 Facebook iOs SDK 登录,它对我来说工作正常。
-(void)openFacebookAuthentication
NSArray *permission = [NSArray arrayWithObjects:kFBEmailPermission,kFBUserPhotosPermission, nil];
FBSession *session = [[FBSession alloc] initWithPermissions:permission];
[FBSession setActiveSession: [[FBSession alloc] initWithPermissions:permission] ];
[[FBSession activeSession] openWithBehavior:FBSessionLoginBehaviorForcingWebView completionHandler:^(FBSession *session, FBSessionState status, NSError *error)
switch (status)
case FBSessionStateOpen:
[self getMyData];
break;
case FBSessionStateClosedLoginFailed:
// prefer to keep decls near to their use
// unpack the error code and reason in order to compute cancel bool
NSString *errorCode = [[error userInfo] objectForKey:FBErrorLoginFailedOriginalErrorCode];
NSString *errorReason = [[error userInfo] objectForKey:FBErrorLoginFailedReason];
BOOL userDidCancel = !errorCode && (!errorReason || [errorReason isEqualToString:FBErrorLoginFailedReasonInlineCancelledValue]);
if(error.code == 2 && ![errorReason isEqualToString:@"com.facebook.sdk:UserLoginCancelled"])
UIAlertView *errorMessage = [[UIAlertView alloc] initWithTitle:kFBAlertTitle
message:kFBAuthenticationErrorMessage
delegate:nil
cancelButtonTitle:kOk
otherButtonTitles:nil];
[errorMessage performSelectorOnMainThread:@selector(show) withObject:nil waitUntilDone:YES];
errorMessage = nil;
break;
// presently extension, log-out and invalidation are being implemented in the Facebook class
default:
break; // so we do nothing in response to those state transitions
];
permission = nil;
【讨论】:
酷,我会尽快尝试并通知您 好的,如果您遇到任何问题,请告诉我。 这会打开一个 webview 进行登录,然后当我使用 uiwebview 转到视图控制器时,我已经登录到 facebook,这很好。问题是,如果我先去 uiwebview 并登录到 facebook,可以将这些数据共享回本机 sdk 吗? 这不是我一直在寻找的,但迄今为止我见过的最佳解决方案,谢谢 @marchinram 关于用户先浏览网页,然后尝试登录 Facebook 的问题,您找到解决方案了吗?【参考方案2】:创建 facebook Appid Facebook Appid creating link 创建时间遵循 facebook 指南,您必须在注册时提供捆绑标识符
然后使用此代码
@interface LoginViewController : UIViewController<UIWebViewDelegate>
@property(nonatomic,retain)UIWebView *webview;
@property (nonatomic, retain) NSString *accessToken;
@property(nonatomic,retain)UIActivityIndicatorView *FbActive;
@end
@interface LoginViewController ()
@end
@implementation LoginViewController
@synthesize accessToken,webview,FbActive;
- (id)initWithNibName:(NSString *)nibNameOrNil bundle:(NSBundle *)nibBundleOrNil
self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
if (self)
// Custom initialization
return self;
- (void)viewDidLoad
[super viewDidLoad];
// Do any additional setup after loading the view.
//Removeing the UIWebview Cookies
NSHTTPCookie *cookie;
NSHTTPCookieStorage *storage = [NSHTTPCookieStorage sharedHTTPCookieStorage];
for (cookie in [storage cookies])
[storage deleteCookie:cookie];
[[NSUserDefaults standardUserDefaults] synchronize];
-(IBAction)fbLoginPage:(UIButton *)sender1
NSString *facebookClientID =facebookAppId;
NSString *redirectUri = @"http://www.facebook.com/connect/login_success.html";
NSString *extended_permissions=@"user_photos,user_videos,publish_stream,offline_access,user_checkins,friends_checkins,email";
NSString *url_string = [NSString stringWithFormat:@"https://graph.facebook.com/oauth/authorize?client_id=%@&redirect_uri=%@&scope=%@&type=user_agent&display=touch", facebookClientID, redirectUri, extended_permissions];
NSURL *url = [NSURL URLWithString:url_string];
NSURLRequest *request = [NSURLRequest requestWithURL:url];
CGRect webFrame =[self.view frame];
webFrame.origin.y = 0;
UIWebView *aWebView = [[UIWebView alloc] initWithFrame:webFrame];
[aWebView setDelegate:self];
self.webview = aWebView;
self.FbActive = [[UIActivityIndicatorView alloc] initWithActivityIndicatorStyle:UIActivityIndicatorViewStyleGray];
self.FbActive.color=[UIColor darkGrayColor];
self.FbActive.center = CGPointMake(self.view.frame.size.width / 2, self.view.frame.size.height / 2);
[self.FbActive startAnimating];
[webview loadRequest:request];
[self.webview addSubview:self.FbActive];
[self.view addSubview:webview];
- (void)webViewDidFinishLoad:(UIWebView *)_webView
/**
* Since there's some server side redirecting involved, this method/function will be called several times
* we're only interested when we see a url like: http://www.facebook.com/connect/login_success.html#access_token=..........
*/
//get the url string
[self.FbActive stopAnimating];
NSString *url_string = [((_webView.request).URL) absoluteString];
//looking for "access_token="
NSRange access_token_range = [url_string rangeOfString:@"access_token="];
//looking for "error_reason=user_denied"
NSRange cancel_range = [url_string rangeOfString:@"error_reason=user_denied"];
//it exists? coolio, we have a token, now let's parse it out....
if (access_token_range.length > 0)
//we want everything after the 'access_token=' thus the position where it starts + it's length
int from_index = access_token_range.location + access_token_range.length;
NSString *access_token = [url_string substringFromIndex:from_index];
//finally we have to url decode the access token
access_token = [access_token stringByReplacingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
//remove everything '&' (inclusive) onward...
NSRange period_range = [access_token rangeOfString:@"&"];
//move beyond the .
access_token = [access_token substringToIndex:period_range.location];
//store our request token....
self.accessToken = access_token;
//remove our window
// UIWindow* window = [UIApplication sharedApplication].keyWindow;
// if (!window)
// window = [[UIApplication sharedApplication].windows objectAtIndex:0];
//
[self.webview removeFromSuperview];
self.webview=nil;
//tell our callback function that we're done logging in :)
// if ( (callbackObject != nil) && (callbackSelector != nil) )
// [callbackObject performSelector:callbackSelector];
//
//the user pressed cancel
else if (cancel_range.length > 0)
//remove our window
// UIWindow* window = [UIApplication sharedApplication].keyWindow;
// if (!window)
// window = [[UIApplication sharedApplication].windows objectAtIndex:0];
//
[self.webview removeFromSuperview];
self.webview=nil;
//tell our callback function that we're done logging in :)
// if ( (callbackObject != nil) && (callbackSelector != nil) )
// [callbackObject performSelector:callbackSelector];
//
[self getuserdetailes];
-(void)getuserdetailes
NSString *action=@"me";
NSString *url_string = [NSString stringWithFormat:@"https://graph.facebook.com/%@?", action];
//tack on any get vars we have...
NSDictionary *get_vars=nil;
if ( (get_vars != nil) && ([get_vars count] > 0) )
NSEnumerator *enumerator = [get_vars keyEnumerator];
NSString *key;
NSString *value;
while ((key = (NSString *)[enumerator nextObject]))
value = (NSString *)[get_vars objectForKey:key];
url_string = [NSString stringWithFormat:@"%@%@=%@&", url_string, key, value];
//end while
//end if
if (accessToken != nil)
//now that any variables have been appended, let's attach the access token....
url_string = [NSString stringWithFormat:@"%@access_token=%@", url_string, self.accessToken];
url_string = [url_string stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding];
NSLog(@"%@",url_string);
NSURLRequest *request = [NSURLRequest requestWithURL:[NSURL URLWithString:url_string]];
NSError *err;
NSURLResponse *resp;
NSData *response = [NSURLConnection sendSynchronousRequest:request returningResponse:&resp error:&err];
NSString *stringResponse = [[NSString alloc] initWithData:response encoding:NSUTF8StringEncoding];
NSLog(@"%@",stringResponse);
NSError* error;
NSDictionary *FBResResjson = [NSJSONSerialization
JSONObjectWithData:response//1
options:kNilOptions
error:&error];
NSLog(@"%@",FBResResjson);
【讨论】:
【参考方案3】:感谢 Divya Bhalodiya 回答。这是带有 Facebook SDK 4.x 的 swift 3 版本。如果代码有任何问题,请随时编辑和评论。希望这会有所帮助。
func verifyFromWebView()
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.loginBehavior = FBSDKLoginBehavior.web
fbLoginManager.logIn(withReadPermissions: ["email"], from: self) (result, error) in
if error != nil
print(error!.localizedDescription)
self.dismiss(animated: true, completion: nil)
else if (result?.isCancelled)!
print("Cancelled")
self.dismiss(animated: true, completion: nil)
else
if let fbLoginResult = result
if fbLoginResult.grantedPermissions != nil && fbLoginResult.grantedPermissions.contains("email")
self.getFBData()
【讨论】:
这可以让用户使用原生 SDK 登录,但您仍然需要登录 webview。因此,此解决方案不再适用于解决 OP 问题。以上是关于Facebook iOS SDK 登录原生和 UIWebView 登录的主要内容,如果未能解决你的问题,请参考以下文章
是否可以在不使用 iOS SDK 的情况下集成 Facebook 登录?