1

我已经尝试了很多来实现将现有解析用户链接到 Facebook。

我正在使用 swift 3。

但我找不到解决方案

我的状态是

  1. 我已经有未关联 Facebook 的帐户。

  2. 我想通过 facebookUtils 链接我的帐户

  3. 我的应用有“登录或注册 Facebook”按钮

  4. 它的工作方式如下

我的问题是

  1. 当我点击 Facebook 登录按钮时,我没有登录。这意味着我没有 PFUser.current()

这是我想要做的

  1. 通过 facebookGraph API 获取电子邮件地址并通过查询电子邮件检查 isUser 与否

  2. 我试过这样登录

尝试!PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)

但它不起作用,因为我无法获得密码。它总是返回 nil

  1. 我曾尝试通过 1 个查询结果获得的链接 PFUser 对象

  2. 我也试过这样的云功能

Parse.Cloud.define("fblink", function(request, response) {

var query = new Parse.Query(Parse.User);
query.equalTo("username", request.params.username);

query.first({
  success: function(object) {

       if (!Parse.FacebookUtils.isLinked(object)) {
              Parse.FacebookUtils.link(object, null, {
                success: function(user) {
                  alert("Woohoo, user logged in with Facebook!");
                    response.success(true);   
                },
                error: function(user, error) {
                  alert("User cancelled the Facebook login or did not fully authorize.");
                    response.success(false);   
                }
              });
            }
  },
  error: function(error) {
    console.log("Error: " + error.code + " " + error.message);
  }
});

});

但它不起作用......我认为云功能方法在这种情况下不是解决方案。

我发现了很多与将现有用户合并到 Facebook authdata 相关的问题。但我找不到任何解决方案。

我希望一起找到好的方法。

func fbBtnTapped() {

        //Show Activity indicator
        let spiningActivity = MBProgressHUD.showAdded(to: self.view, animated: true)
        spiningActivity?.labelText = "Loading"
        spiningActivity?.detailsLabelText = "Please Wait"


        let permissions = ["public_profile", "email"]


        PFFacebookUtils.logInInBackground(withReadPermissions: permissions, block: {(user:PFUser?, error:Error?) -> Void in

            if let user = user {
                if user.isNew {
                    print("User signed up and logged in through Facebook!")

                } else {
                    print("User logged in through Facebook!")
                }
            } else {
                print("Uh oh. The user cancelled the Facebook login.")

            }


            if(error != nil)
            {
                spiningActivity?.hide(true)

                print("in FBBUTTONTapped Error")
                // display an error message
                let userMessage = error!.localizedDescription
                let myAlert = UIAlertController(title: "Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                myAlert.addAction(okAction)

                self.present(myAlert, animated: true, completion: nil)
                return
            }

            // Load facebook details like userName, email address, profile picture.
            self.loadFacebookUserDetails()


        })



    }

这是我在 loadFacebookUserDetails 中尝试过的。

func loadFacebookUserDetails()
    {
        MBProgressHUD.hideAllHUDs(for: self.view, animated: true)

        //Show Activity indicator
        let spiningActivity = MBProgressHUD.showAdded(to: self.view, animated: true)
        spiningActivity?.labelText = "Loading"
        spiningActivity?.detailsLabelText = "Wait"


        //Define fields we would like to read from Facebook User Object
        let requestParameters = ["fields": "id, email, first_name, last_name"]
        // me
        let userDetails : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: requestParameters)

        userDetails.start(completionHandler: { (connection, result, error) -> Void in

            if error != nil {


                print("in FBDetailed Error")
                //Display error message
                spiningActivity?.hide(true)

                let userMessage = error!.localizedDescription
                let myAlert = UIAlertController(title:"Alert", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                myAlert.addAction(okAction)

                self.present(myAlert, animated: true, completion: nil)

                PFUser.logOut()

                return

            }

            var userId = String()
            var userName = String()
            var userEmail = String()
            var userFirstName = String()
            var userLastName = String()
            var displayName = String()

            var userObj = PFUser()

            //Extract user fields
            if let dict = result as? [String: AnyObject]
            {
                userId = dict["id"] as! String
                print("User id=\(userId)")
                userEmail = (dict["email"] as? String)!
                print("User email=\(userEmail)")

                userFirstName = dict["first_name"] as! String
                print("User FirstName=\(userFirstName)")
                userLastName = dict["last_name"] as! String
                print("User LastName=\(userLastName)")
            }

            //get Username
            if !userEmail.isEmpty
            {
                PFUser.current()?.email = userEmail
                if let range = userEmail.range(of: "@") {

                    let username = userEmail.substring(to: range.lowerBound)
                    userName = username

                    PFUser.current()?.username = username
                }
            }

            PFFacebookUtils.linkUser(inBackground: PFUser.current()!, with: FBSDKAccessToken.current())


            //Get Facebook profile picture
            let userProfile = "https://graph.facebook.com/" + userId + "/picture?type=large"

            let profilePictureUrl = URL(string:userProfile)
            let profilePictureData = try? Data(contentsOf: profilePictureUrl!)

            //Prepare PFUser object
            if(profilePictureData != nil)
            {
                let profileFileObject = PFFile(data:profilePictureData!)

                //                userObj.setObject(profileFileObject!, forKey: "profileImg")

                if (PFUser.current()?.object(forKey: "profileImg")) == nil{

                    PFUser.current()?.setObject(profileFileObject!, forKey: "profileImg")
                }
            }

            displayName=userFirstName+userLastName
            PFUser.current()?.setObject(displayName, forKey: "displayname")



            //Check If user has already signedup or not
            let query = PFQuery(className: "_User")
            query.whereKey("username", equalTo: userName)
            try! userObj = query.getFirstObject() as! PFUser

//            if userObj.username != nil {
//                
//                print("already signed up")
//                return
//            }
//            print(FBSDKAccessToken.current())



//            try! PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)

            PFFacebookUtils.linkUser(inBackground: PFUser.current()!, with: FBSDKAccessToken.current())


//            userObj.setObject(displayName, forKey: "displayname")

            PFUser.current()?.saveInBackground(block: { (success:Bool, error:Error?) in
                spiningActivity?.hide(true)

                if(error != nil)
                {
                    let userMessage = error!.localizedDescription
                    let myAlert = UIAlertController(title: "Alert2", message: userMessage, preferredStyle: UIAlertControllerStyle.alert)

                    let okAction = UIAlertAction(title: "Ok", style: UIAlertActionStyle.default, handler: nil)

                    myAlert.addAction(okAction)

                    self.present(myAlert, animated: true, completion: nil)

                    PFUser.logOut()
                    return
                }

                if(success)
                {
                    if !userId.isEmpty
                    {
                        print(userId)
                        //userId->userName
                        UserDefaults.standard.set(userName, forKey: "username")
                        UserDefaults.standard.synchronize()

                        DispatchQueue.main.async{
                            let appDelegate:AppDelegate = UIApplication.shared.delegate as! AppDelegate

                            appDelegate.buildUserInterface()
                        }

                    }

                }
            })
//



        })



    }
4

1 回答 1

3

PFUser.current()如果他不是 Facebook 链接帐户,您将需要能够链接该帐户。您的选择是:

1 :) 使用您的逻辑通过登录页面使用 facebook 登录。这意味着您在该Users列中有一个新用户。所以本质上,不管以后如何,它都可以用作parse登录。您可以使用电子邮件或 facebook 名称更新用户名(因为ID默认情况下,facebook 登录将使用 填充用户名)。一旦他进入成功页面,如果他以后选择不使用他的 facebook 帐户,您可以要求他填写密码以供以后使用。然后欢迎他在设置页面中使用取消链接按钮取消链接帐户。

@IBAction func unlinkFacebook(_ sender: AnyObject) {
    let user = PFUser.current()
    showHUD(message: "unlinking")
    PFFacebookUtils.unlinkUser(inBackground: user!, block:{
        (succeeded: Bool?, error) -> Void in
        if succeeded! {
            self.simpleAlert(mess: "Your account is no longer associated with your Facebook account.")
            self.hideHUD()

        }else{
            self.simpleAlert(mess: "\(error!.localizedDescription)")
            self.hideHUD()
        }
    })
}

所有取消链接都会清除该authData列。

2:) 以解析用户身份登录,一旦成功登录,请他将他的帐户链接到 facebook。一个func可能像:

func linkFacebook() {
   let user = PFUser.current()
    showHUD(message: "linking")
    if !PFFacebookUtils.isLinked(with: user!) {
        PFFacebookUtils.linkUser(inBackground:  user!, withReadPermissions: nil, block:{
            (succeeded: Bool?, error) -> Void in
            if succeeded! {
             self.simpleAlert(mess: "Success. You can now log in using your facebook account in future.")
             self.hideHUD()
            }else{
             self.simpleAlert(mess: "\(error!.localizedDescription)")
             self.hideHUD()
            }
        })
    }
}

可以将它放在您的viewdidLoad或一个不错的按钮中,如果用户选择要链接他的帐户,则可以选择该按钮。sdk请记住,如果要存储 Facebook 详细信息,则需要调用 Facebook以更新用户详细信息。

只有在 中填充的列Users tableauthData

于 2016-12-12T06:43:21.993 回答