如果我在 Xcode 中创建了一个 UIView
,然后将自定义类添加为 FBSDKLoginButton
,当我点击它时,它会引导我通过 Facebook 登录,然后返回到与 FBSDKLoginButton
相同的页面,但不再显示登录按钮,而是显示“现在注销”。我该如何让它在单击登录按钮时跳转到新视图?
我通过 CocoaPods 下载了 Facebook SDK,并且这是我第一次使用它,所以我对此感到困惑。感谢您的帮助!
如果我在 Xcode 中创建了一个 UIView
,然后将自定义类添加为 FBSDKLoginButton
,当我点击它时,它会引导我通过 Facebook 登录,然后返回到与 FBSDKLoginButton
相同的页面,但不再显示登录按钮,而是显示“现在注销”。我该如何让它在单击登录按钮时跳转到新视图?
我通过 CocoaPods 下载了 Facebook SDK,并且这是我第一次使用它,所以我对此感到困惑。感谢您的帮助!
FBSDKLoginButton
的代理,并实现loginButton:didCompleteWithResult:error:
方法,该方法在使用按钮登录时调用。
Swift
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
@IBOutlet weak var loginButton: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
self.loginButton.delegate = self
}
}
// ViewController.h
@interface ViewController : UIViewController <FBSDKLoginButtonDelegate>
@property (weak, nonatomic) IBOutlet FBSDKLoginButton *loginButton;
@end
// ViewController.m
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
self.loginButton.delegate = self;
}
loginButton:didCompleteWithResult:error:
方法中,您可以检查result
和error
,如果一切正常,导航到另一个视图。
Swift
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if ((error) != nil) {
// Process error
}
else if result.isCancelled {
// Handle cancellations
}
else {
// Navigate to other view
}
}
// ViewController.m
@implementation ViewController
- (void)loginButton:(FBSDKLoginButton *)loginButton
didCompleteWithResult:(FBSDKLoginManagerLoginResult *)result
error:(NSError *)error {
if (error) {
// Process error
}
else if (result.isCancelled) {
// Handle cancellations
}
else {
// Navigate to other view
}
}
class MyViewController: UIViewController, FBSDKLoginButtonDelegate {
@IBOutlet weak var loginView : FBSDKLoginButton!
@IBOutlet weak var profilePictureView : FBSDKProfilePictureView!
override func viewDidLoad() {
super.viewDidLoad()
self.loginView.delegate = self
if (FBSDKAccessToken.currentAccessToken() != nil)
{
performSegueWithIdentifier("unwindToViewOtherController", sender: self)
}
else
{
loginView.readPermissions = ["public_profile", "email", "user_friends"]
}
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
println("User Logged In")
if ((error) != nil)
{
// Process error
}
else if result.isCancelled {
// Handle cancellations
}
else {
// If you ask for multiple permissions at once, you
// should check if specific permissions missing
if result.grantedPermissions.contains("email")
{
// Do work
}
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
println("User Logged Out")
}
}
然后,在您的TargetViewController中添加一个取消操作函数:
@IBAction func unwindToViewOtherController(segue:UIStoryboardSegue) {
}
if (FBSDKAccessToken.currentAccessToken() != nil)
里面的 performSegueWithIdentifier("unwindToViewOtherController", sender: self)
没有加载下一个视图控制器,请问可以帮忙解决吗? - rAzOrunwindToViewOtherController
作为 标识符 和 unwindToViewOtherController:
作为 操作。 - Ruud KalisviewDidAppear
函数并在其中编写 performSegueWithIdentifier
。这解决了问题。我们不能在 viewDidLoad
函数中使用 performSegueWithIdentifier
,这是我从谷歌学到的。请问您能帮我知道为什么吗? - rAzOrViewDidLoad
函数执行完毕后,视图才会被呈现出来,因此才能被关闭。 - Ruud Kalispublic class LoginButton: UIView {
...
/// Delegate of the login button that can handle the result, logout events.
public var delegate: LoginButtonDelegate?
... }
UIViewController
子类设置为按钮代理...import FacebookLogin
func viewDidLoad() {
let loginButton = LoginButton(readPermissions: [ .PublicProfile ])
loginButton.center = view.center
loginButton.delegate = self
view.addSubview(loginButton)
}
如果不小心出现循环引用,就会创建一个引用循环。视图将包含对按钮的强引用,按钮将包含对控制器的强引用,控制器将对其视图保持强引用,请参见此帖子。
我的解决方案是使用一个弱成员变量来引用登录按钮,当视图消失时,将按钮委托设置为nil,如下所示:
import UIKit
import FacebookCore
import FacebookLogin
import RxSwift
class LoginViewController: UIViewController, LoginButtonDelegate {
private weak var facebookLoginButton: LoginButton? = nil
override func viewDidLoad() {
super.viewDidLoad()
// Add the Facebook login button
let loginButton = LoginButton(readPermissions: [ .publicProfile, .email, .userFriends ])
loginButton.center = view.center
// WARNING!: Facebook login button delegate property is defined currently as STRONG.
// Therefore, it must be set to nil before leaving the view to avoid reference cycles
loginButton.delegate = self
view.addSubview(loginButton)
// Store the login button as a weak reference, since it is holded by the main view with a
// strong reference
facebookLoginButton = loginButton
}
override func willMove(toParentViewController parent: UIViewController?) {
super.willMove(toParentViewController:parent)
if parent == nil {
// The back button was pressed, interactive gesture used, or programatically pop view
// was executed
// Do not forget to set delegate in Facebook button to nil to break reference cycle.
facebookLoginButton?.delegate = nil
}
}
// MARK: - Facebook login
/**
Called when the button was used to login and the process finished.
- parameter loginButton: Button that was used to login.
- parameter result: The result of the login.
*/
func loginButtonDidCompleteLogin(_ loginButton: LoginButton, result: LoginResult) {
switch result {
case .failed(let error):
// Action on failed
case .cancelled:
// Action on cancelled
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
// Action on success
}
}
/**
Called when the button was used to logout.
- parameter loginButton: Button that was used to logout.
*/
func loginButtonDidLogOut(_ loginButton: LoginButton) {
// Action on logout
}
}
viewWillDissapear()
来设置委托为nil
,因为Facebook登录页面将显示在您的应用程序顶部,触发此功能,并且您将不再是委托,因此将无法获取登录结果。 请注意,此解决方案适用于导航控制器中的视图。 对于模态窗口,应找到另一种解决方案。IOS 13使用场景委托(Scene Delegate)。只需将下面的代码粘贴到场景委托中,简单调用Facebook登录管理器,它将返回Facebook用户对象。此函数会自动调用。
func scene(_ scene: UIScene, openURLContexts URLContexts: Set<UIOpenURLContext>) {
guard let url = URLContexts.first?.url else {
return
}
let _ = ApplicationDelegate.shared.application(
UIApplication.shared,
open: url,
sourceApplication: nil,
annotation: [UIApplication.OpenURLOptionsKey.annotation])
}
你可以像appcoda的教程中所示这样做(见下面的代码)
- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"Facebook Profile";
// Check if user is cached and linked to Facebook, if so, bypass login
if ([PFUser currentUser] && [PFFacebookUtils isLinkedWithUser:[PFUser currentUser]]) {
[self.navigationController pushViewController: [[UserDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped] animated:NO];
}
}
#pragma mark - Login methods
/* Login to facebook method */
- (IBAction)loginButtonTouchHandler:(id)sender {
// Set permissions required from the facebook user account
NSArray *permissionsArray = @[ @"user_about_me", @"user_relationships", @"user_birthday", @"user_location"];
// Login PFUser using facebook
[PFFacebookUtils logInWithPermissions:permissionsArray block:^(PFUser *user, NSError *error) {
[_activityIndicator stopAnimating]; // Hide loading indicator
if (!user) {
if (!error) {
NSLog(@"Uh oh. The user cancelled the Facebook login.");
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Log In Error" message:@"Uh oh. The user cancelled the Facebook login." delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Dismiss", nil];
[alert show];
} else {
NSLog(@"Uh oh. An error occurred: %@", error);
UIAlertView *alert = [[UIAlertView alloc] initWithTitle:@"Log In Error" message:[error description] delegate:nil cancelButtonTitle:nil otherButtonTitles:@"Dismiss", nil];
[alert show];
}
} else if (user.isNew) {
NSLog(@"User with facebook signed up and logged in!");
[self.navigationController pushViewController:[[UserDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped] animated:YES];
} else {
NSLog(@"User with facebook logged in!");
[self.navigationController pushViewController:[[UserDetailsViewController alloc] initWithStyle:UITableViewStyleGrouped] animated:YES];
}
}];
[_activityIndicator startAnimating]; // Show loading indicator until login is finished
}
这里有一个演示应用程序。