简体   繁体   English

Swift 的 Facebook 登录按钮

[英]Facebook Login button for Swift

In Xcode if I create a UIView and then add the custom class as FBSDKLoginButton , when I click it leads me through the Facebook login and then returns me to the same page as the FBSDKLoginButton but instead of saying login button it says log out now.在 Xcode 中,如果我创建一个UIView然后将自定义类添加为FBSDKLoginButton ,当我单击它时会引导我完成 Facebook 登录,然后将我返回到与FBSDKLoginButton相同的页面,但不是说登录按钮,而是说现在注销。 How would I go about making that when the login button is clicked it lead to a new view?当单击登录按钮时,我将如何进行它导致一个新视图?


I downloaded the Facebook SDK through cocoapods and its my first time working with it so I am confused about this.我通过 cocoapods 下载了 Facebook SDK,这是我第一次使用它,所以我对此感到困惑。 Thanks for the help!谢谢您的帮助!

One option would be to set your view controller as a delegate of the FBSDKLoginButton and implement the loginButton:didCompleteWithResult:error: method, which is called when the button is used to login.一种选择是将您的视图控制器设置为FBSDKLoginButton的委托并实现loginButton:didCompleteWithResult:error:方法,该方法在按钮用于登录时调用。

Swift迅速

class ViewController: UIViewController, FBSDKLoginButtonDelegate {

    @IBOutlet weak var loginButton: FBSDKLoginButton!        

    override func viewDidLoad() {
        super.viewDidLoad()

        self.loginButton.delegate = self
    }
}

Obj-C对象-C

// 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;
}

Then, in the loginButton:didCompleteWithResult:error: method you can check the result and error , and if everything is fine, navigate to another view.然后,在loginButton:didCompleteWithResult:error:方法中,您可以检查resulterror ,如果一切正常,则导航到另一个视图。

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
        }   
    }

Obj-C对象-C

// 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
    }
}

You can find more about how to login with FB in their docs .您可以在 他们的文档中找到有关如何使用 FB 登录的更多信息。

In Swift that would be something like:在 Swift 中,这将类似于:

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")
    }
}

Then in your TargetViewController add an unwind function:然后在你的 TargetViewController 添加一个 unwind 函数:

@IBAction func unwindToViewOtherController(segue:UIStoryboardSegue) {
    }

In current FacebookLogin version (0.2.0) for Swift, the LoginButton delegate property is defined as a strong property:在 Swift 的当前 FacebookLogin 版本 (0.2.0) 中,LoginButton 委托属性被定义为一个强属性:

public class LoginButton: UIView {
...
  /// Delegate of the login button that can handle the result, logout events.
public var delegate: LoginButtonDelegate?
... }

If you add the login button following Facebook instructions and you set your UIViewController child class as button delegate...如果您按照 Facebook 说明添加登录按钮,并将您的UIViewController子类设置为按钮委托......

import FacebookLogin

func viewDidLoad() {
    let loginButton = LoginButton(readPermissions: [ .PublicProfile ])
    loginButton.center = view.center
    loginButton.delegate = self
    view.addSubview(loginButton)
}

... a reference cycle will be created. ... 将创建一个参考循环。 The view will contain a strong reference to the button, the button will contain a strong reference to the controller, and the controller will have a strong reference to its view, see this post .视图将包含对按钮的强引用,按钮将包含对控制器的强引用,而控制器将对其视图具有强引用,请参阅此帖子

My solution was to use a weak member variable to have a reference to the login button and when the view disappears, the button delegate is set to nil, like this:我的解决方案是使用弱成员变量来引用登录按钮,当视图消失时,按钮委托设置为 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
    }
}

Do not use function viewWillDissapear() for setting to nil the delegate, because Facebook login page will be shown on top of your app, triggering this function, and you will not get the login result since you will not be the delegate anymore.不要使用函数viewWillDissapear()设置为nil委托,因为 Facebook 登录页面将显示在您的应用程序顶部,触发此功能,您将不会获得登录结果,因为您不再是委托人。 Note that this solution is working fine for views inside a navigation controller.请注意,此解决方案适用于导航控制器内的视图。 Another solution should be found for modal windows.应该为模态窗口找到另一个解决方案。

I hope it helps, Xavi我希望它有帮助,哈维

IOS 13 use Scene Delegate. IOS 13 使用场景委托。 Just paste the below code in scene delegate and simple call the facebook login manager it will return the user object of facebook.只需将以下代码粘贴到场景委托中,然后简单地调用 facebook 登录管理器,它将返回 facebook 的用户对象。 This function automatically call.该函数自动调用。

 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])
    }

You could do this like this tutorial from appcoda (see code below)您可以从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
}

Here is a demo app for this.这是一个演示应用程序

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM