如何通过 FacebookUtil link 解析现有用户
How to link existing Parse User via FacebookUtil
我已经尝试了很多来实现 link Facebook 的现有解析用户。
我正在使用 swift 3.
但我找不到解决方案
我的状态是
我已经没有 link Facebook 帐户。
我想通过 facebookUtilslink 我的帐户
我的应用有 "Sign In or SignUp Facebook" 按钮
它的工作原理如下
我的问题是
- 我点击 Facebook 登录按钮后没有登录。这意味着我没有 PFUser.current()
这是我正在尝试做的事情
通过 facebookGraph 获取电子邮件地址 API 并通过查询电子邮件来检查是否是用户
我试过这样登录
试试吧! PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)
但它不起作用,因为我无法获取密码。它总是返回 nil
我试过 link PFUser 对象,我通过 1 个查询结果
我也试过这样的云函数
Parse.Cloud.define("fblink", 函数(请求, 响应) {
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 授权数据相关的问题。但是我找不到任何解决方案。
希望大家一起找到好的方法。
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()
}
}
}
})
//
})
}
如果他不是 Facebook linked 帐户,您将需要 PFUser.current()
帐户才能 link。您的选择是:
1:) 使用您的逻辑通过登录页面登录 facebook。这意味着您在 Users
列中有一个新用户。因此,无论以后如何,基本上都可以用作 parse
登录。您可以只用电子邮件或 Facebook 名称更新用户名(因为默认情况下,Facebook 登录会用 ID
填充用户名)。一旦他进入成功页面,您可以让他填写一个密码,以备日后他选择不使用他的 facebook 帐户时使用。然后欢迎他使用取消link按钮取消link设置页面中的帐户。
@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()
}
})
}
所有未linking 将做的就是清除 authData
列。
2:) 以 parse 用户身份登录,成功登录后请他link 将他的帐户转到 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
或一个漂亮的按钮中,让用户可以选择是否要 link 他的帐户。请记住,如果您想存储 Facebook 详细信息,您需要调用 Facebook sdk
来更新用户详细信息。
Users table
中唯一填充的列是 authData
。
我已经尝试了很多来实现 link Facebook 的现有解析用户。
我正在使用 swift 3.
但我找不到解决方案
我的状态是
我已经没有 link Facebook 帐户。
我想通过 facebookUtilslink 我的帐户
我的应用有 "Sign In or SignUp Facebook" 按钮
它的工作原理如下
我的问题是
- 我点击 Facebook 登录按钮后没有登录。这意味着我没有 PFUser.current()
这是我正在尝试做的事情
通过 facebookGraph 获取电子邮件地址 API 并通过查询电子邮件来检查是否是用户
我试过这样登录
试试吧! PFUser.logIn(withUsername: userObj.username!, password: userObj.password!)
但它不起作用,因为我无法获取密码。它总是返回 nil
我试过 link PFUser 对象,我通过 1 个查询结果
我也试过这样的云函数
Parse.Cloud.define("fblink", 函数(请求, 响应) {
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 授权数据相关的问题。但是我找不到任何解决方案。
希望大家一起找到好的方法。
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()
}
}
}
})
//
})
}
如果他不是 Facebook linked 帐户,您将需要 PFUser.current()
帐户才能 link。您的选择是:
1:) 使用您的逻辑通过登录页面登录 facebook。这意味着您在 Users
列中有一个新用户。因此,无论以后如何,基本上都可以用作 parse
登录。您可以只用电子邮件或 Facebook 名称更新用户名(因为默认情况下,Facebook 登录会用 ID
填充用户名)。一旦他进入成功页面,您可以让他填写一个密码,以备日后他选择不使用他的 facebook 帐户时使用。然后欢迎他使用取消link按钮取消link设置页面中的帐户。
@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()
}
})
}
所有未linking 将做的就是清除 authData
列。
2:) 以 parse 用户身份登录,成功登录后请他link 将他的帐户转到 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
或一个漂亮的按钮中,让用户可以选择是否要 link 他的帐户。请记住,如果您想存储 Facebook 详细信息,您需要调用 Facebook sdk
来更新用户详细信息。
Users table
中唯一填充的列是 authData
。