Get Info and Image with facebook authentication - SWIFT FacebookSDK - swift

I'm trying to learn something about swift and facebook.
I integrated the SDK manually without using the pods and so far everything is ok!
I created a LogIn button by following some online guides and this works too!
Through this code located in the ViewController I can also print Id, First_Name, Last_Name and receive the ProfilePicture info :
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if (error == nil) {
print("Connected")
let r = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"email,first_name,last_name,picture.type(large)"], tokenString: FBSDKAccessToken.current()?.tokenString, version: nil, httpMethod: "GET")
r?.start(completionHandler: { (test, result, error) in
if(error == nil)
{
print(result as Any)
}
})
} else
{
print(error.localizedDescription)
}
}
func loginButtonWillLogin(_ loginButton: FBSDKLoginButton!) -> Bool {
return true
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("Disconnected")
}
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
let loginButton = FBSDKLoginButton()
loginButton.readPermissions = ["public_profile", "email"]
loginButton.center = self.view.center
loginButton.delegate = self
self.view.addSubview(loginButton)
}
}
The OutPut is this :
Optional({
email = "cxxxxxxxxx2#live.it";
"first_name" = Cxxxxxe;
id = 10xxxxxxxxxxxxx75;
"last_name" = Lxxxxxo;
picture = {
data = {
height = 200;
"is_silhouette" = 0;
url = "https://platform-lookaside.fbsbx.com/platform/profilepic/?asid=10xxxxxxxxxxxxx75&height=200&width=200&ext=1565467901&hash=AeQ-NalWNEMh91CK";
width = 200;
};
};
})
Now I don't know how to extract a single information such as the first_name in a variable to be able to print it in a label or take the url of the image to print it in the app.
if I try to change inside the login function like this :
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if (error == nil) {
print("Connected")
let r = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"email,first_name,last_name,picture.type(large)"], tokenString: FBSDKAccessToken.current()?.tokenString, version: nil, httpMethod: "GET")
r?.start(completionHandler: { (test, result, error) in
if(error == nil)
{
print(result!["first_name"] as Any)
}
})
} else
{
print(error.localizedDescription)
}
}
the compiler tells me : "Value of type 'Any' has no subscripts".
How can i do this?
Thanks ;)

in the result you should put
result.user
and that object is the one that contains the properties like displayName, or firstName for this matter

I created the labels and for now I solved it this way:
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if (error == nil) {
print("Connected")
let r = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"email,first_name,last_name,picture.type(large)"], tokenString: FBSDKAccessToken.current()?.tokenString, version: nil, httpMethod: "GET")
r?.start(completionHandler: { (test, result, error) in
if let id : NSString = (result! as AnyObject).value(forKey: "id") as? NSString {
print("id: \(id)")
self.lbl_fbid.text = "ID: \(id)"
}
if let first_name : NSString = (result! as AnyObject).value(forKey: "first_name") as? NSString {
print("first_name: \(first_name)")
self.lbl_fbdirstname.text = "First_Name: \(first_name)"
}
if let last_name : NSString = (result! as AnyObject).value(forKey: "last_name") as? NSString {
print("last_name: \(last_name)")
self.lbl_fblastname.text = "First_Name: \(last_name)"
}
if let email : NSString = (result! as AnyObject).value(forKey: "email") as? NSString {
print("email: \(email)")
self.lbl_fbemail.text = "Email: \(email)"
}
})
} else
{
print(error.localizedDescription)
}
}
Now I just have to figure out how to take the profile pic...

All done... if someone need the code i wrote this:
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if (error == nil) {
print("Connected")
let r = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"email,first_name,last_name,picture.type(large)"], tokenString: FBSDKAccessToken.current()?.tokenString, version: nil, httpMethod: "GET")
r?.start(completionHandler: { (test, result, error) in
if let id : NSString = (result! as AnyObject).value(forKey: "id") as? NSString {
print("id: \(id)")
self.lbl_fbid.text = "ID: \(id)"
}
if let imageURL = (((((result! as AnyObject).value(forKey: "picture")) as AnyObject).value(forKey: "data")) as AnyObject).value(forKey: "url") as? NSString{
print("img url: \(imageURL)")
let url = URL(string: imageURL as String)
DispatchQueue.global().async {
let data = try? Data(contentsOf: url!)
DispatchQueue.main.async {
self.img_fbprofilepic.image = UIImage(data: data!)
}
}
}
if let first_name : NSString = (result! as AnyObject).value(forKey: "first_name") as? NSString {
print("first_name: \(first_name)")
self.lbl_fbdirstname.text = "First_Name: \(first_name)"
}
if let last_name : NSString = (result! as AnyObject).value(forKey: "last_name") as? NSString {
print("last_name: \(last_name)")
self.lbl_fblastname.text = "First_Name: \(last_name)"
}
if let email : NSString = (result! as AnyObject).value(forKey: "email") as? NSString {
print("email: \(email)")
self.lbl_fbemail.text = "Email: \(email)"
}
if(error == nil)
{
print(result as Any)
}
})
} else {
print(error.localizedDescription)
}
}

Related

How to set user name to UITextField from FBSDKGraphRequest result

I am using Xcode 10, Swift 5 and I am trying to set a UITextField to just the user name I retrieved from Facebook. I have successfully retrieved the ID, Email, and Name in result but when I sent result to the text field is includes all three fields. I just want the name.
func getUserProfile() {
let req = FBSDKGraphRequest(graphPath: "me", parameters: ["fields":"name"], tokenString: accessToken?.tokenString, version: nil, httpMethod: "GET")
req?.start(completionHandler: { (connection, result, error : Error!) -> Void in
if(error == nil)
{
print("\(String(describing: result))")
self.FBUserName.text = "name \(String(describing: result))"
}
else
{
print("error \(String(describing: error))")
}
})
}
You can cast result to [String : Any], like so
if error != nil {
print("Error: \(error!.localizedDescription)")
} else if let result = result as? [String : Any] {
self.FBUserName.text = result["name"] as! String
}
Here is my working request
let graphRequest: FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "email,name"])
graphRequest.start(completionHandler: { [weak self] (connection, result, error) -> Void in
if error != nil {
print("Error: \(error!.localizedDescription)")
} else if let result = result as? [String : Any], let strongSelf = self {
strongSelf.txtName.text = (result["name"] as! String)
strongSelf.txtEmail.text = (result["email"] as! String)
}
})

UserInfo={NSLocalizedDescription=The email address is already in use by another account., error_name=ERROR_EMAIL_ALREADY_IN_USE}

Hey guys actually i am trying two things here:- trying to create a new account and trying to open a screen like which appears after login but it is showing "email already exist error".
#IBAction func CreateAcccountButton(_ sender: AnyObject) {
guard let eventInterest = textBox.text,let email = EmailTestfield.text, let password = PasswordTestfield.text, let name = UsernameTestfield.text else {
print("Form is not valid")
return
}
Auth.auth().createUser(withEmail: email, password: password, completion: { (user, error) in
if let error = error {
print(error)
return
}
guard let uid = user?.uid else {
return
}
//successfully authenticated user
let imageName = UUID().uuidString
let storageRef = Storage.storage().reference().child("profile_images").child("\(imageName).png")
if let uploadData = UIImagePNGRepresentation(self.Profilepicture.image!) {
storageRef.putData(uploadData, metadata: nil, completion: { (metadata, error) in
if let error = error {
print(error)
return
}
print (metadata)
// let downloadURL = metadata?.downloadURL()
// print("URL ", downloadURL)
if let Profilepictureurl = metadata?.downloadURL()?.absoluteString {
let values = ["name": name, "email": email,"EventInterest":eventInterest,"Password":password,"Profilepictureurl": Profilepictureurl ]
let user = User(dictionary: values as [String : AnyObject])
let customViewController = MessagesController()
customViewController.setupNavBarWithUser(user)
customViewController.fetchUserAndSetupNavBarTitle()
// customViewController.navigationItem.title = values["name"] as? String
self.dismiss(animated: true, completion: nil)
self.registeruserintoDb(uid,values: values as [String : AnyObject])
}
})
}
}
)
}
fileprivate func registeruserintoDb(_ uid: String, values: [String: AnyObject]) {
let ref = Database.database().reference()
let usersReference = ref.child("users").child(uid)
usersReference.updateChildValues(values, withCompletionBlock: { (err, ref) in
if err != nil {
print(err!)
return
}
})
}
It's exactly what the error says, you already have a user with that email. Instead, use the auth.signIn method and check for currently signed in users.

store facebook information into Firebase Database using Facebook IOS swift SDK

I'm trying to store facebook user data into firebase database but I keep getting the error "Cannot convert Any? to expected type String"
((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil && result != nil) {
guard let fbData = result as? [String:Any] else { return }
let fbid = fbData["id"]
let name = fbData["name"]
self.ref.child("users").child(fbid).setValue([
"id": fbid,
"name": name
])
}
})
I also want to store the picture url into the database. How can I do this?
Using Facebook IOS Swift SDK and Firebase
Try my I implement this function. This is from the production app and it works well for us. I also recommend uploading profile image in Firebase storage or other storage, because after a while the profile image url is not valid.
class func getAllFacebookData(success: ((_ result: [String : Any]) -> Void)?, fail: ((_ error: Error) -> Void)?) {
guard !isGetDataFromFacebook else { return }
DispatchQueue.global(qos: .background).async {
guard let tokenString = FBSDKAccessToken.current()?.tokenString else { return }
guard let req = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "name,age_range,birthday,gender,email,first_name,last_name,picture.width(1000).height(1000),work,education,hometown,location, friends"], tokenString: tokenString, version: nil, httpMethod: "GET") else { return }
req.start { (connection, result, error) in
if error == nil {
guard let _result = result as? [String : Any] else { return }
let _picture = _result["picture"] as? [String : Any]
let _pictureData = _picture?["data"] as? [String : Any]
let _isSilhouette = _pictureData?["is_silhouette"] as? Bool
let userPref = UserDefaults.standard
userPref.set(_isSilhouette, forKey: "UserHasSilhouetteImage")
userPref.synchronize()
debugPrint("facebook result", _result)
isGetDataFromFacebook = true
syncUserInfoInDatabase(_result)
success?(_result)
} else {
debugPrint("request", error!)
fail?(error!)
}
}
}
}
fileprivate class func syncUserInfoInDatabase(_ userInfo: [String : Any]) {
let realmManager = RealmManager()
guard let currentUser = realmManager.getCurrentUser() else { return }
guard let userInfoModel = createUserInfoModel(userInfo) else { return }
do {
let realm = try Realm()
try realm.write {
currentUser.info = userInfoModel
}
} catch {
debugPrint("realm syncUserInfoInDatabase error", error.localizedDescription)
}
savePhoto(userInfo)
let firebaseDatabaseGeneralManager = FirebaseDatabaseGeneralManager()
firebaseDatabaseGeneralManager.updateCurrentUser(success: nil, fail: nil)
// crete a personal settings
let firUserSettingsDatabaseManager = FIRUserSettingsDatabaseManager()
firUserSettingsDatabaseManager.createStartPeopleFilterSettings(success: nil, fail: nil)
let userSearchLocationModel = UserSearchLocationModel()
userSearchLocationModel.userID = currentUser.id
userSearchLocationModel.birthdayTimeStamp = currentUser.birthdayTimeStamp
userSearchLocationModel.gender = currentUser.gender
switch currentUser.gender {
case UserPeopleFilterSettings.FilterGenderMode.female.description:
userSearchLocationModel.genderIndex = UserPeopleFilterSettings.FilterGenderMode.female.index
case UserPeopleFilterSettings.FilterGenderMode.male.description:
userSearchLocationModel.genderIndex = UserPeopleFilterSettings.FilterGenderMode.male.index
default: break
}
let firPeopleSearchDatabaseManager = FIRPeopleSearchDatabaseManager()
firPeopleSearchDatabaseManager.saveUserSearchLocationModel(userSearchLocationModel, success: nil, fail: nil)
}
private class func savePhoto(_ userInfo: [String : Any]) {
if let pictureDict = userInfo["picture"] as? [String : Any], let pictureDataDict = pictureDict["data"] as? [String : Any] {
if let urlPath = pictureDataDict["url"] as? String {
let firImageDatabaseManager = FIRImageDatabaseManager()
firImageDatabaseManager.saveProfileImage(urlPath, fileName: nil, isFacebookPhoto: true, realmSaved: nil)
}
}
}

FaceBook Image Upload In API in iOS swift

I am new in iOS . i am trying to convert image or image url into png,or jpg format and failed .plz help me in this matter
#IBAction func FBSignInAct(sender: AnyObject) {
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager .logInWithReadPermissions(["email"], fromViewController: self, handler: { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result
if result.isCancelled {
return
}
if(fbloginresult.grantedPermissions.contains("email"))
{
self.getFBUserData()
}
}
})
}
func getFBUserData(){
if((FBSDKAccessToken.currentAccessToken()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).startWithCompletionHandler({ (connection, result, error) -> Void in
if (error == nil){
print(result)
let url = NSURL(string: result["picture"]!!["data"]!!["url"]!! as! String)
let email:String = result["email"] as! String
let id:String = result["id"] as! String
let name:String = result["name"] as! String
self.signUpFBControl(email , fbID: id , name: name , profile_PicUrl: url!)
}
})
}
}
func signUpFBControl(email:String,fbID:String,name:String,profile_PicUrl:NSURL)
{
let data = NSData(contentsOfURL: profile_PicUrl)
let profilePic : UIImage = UIImage(data: data!)!
let image:NSData = UIImageJPEGRepresentation(profilePic,1)!
let strBase64:String = image.base64EncodedStringWithOptions(.Encoding64CharacterLineLength)
print(strBase64)
let dataDecoded:NSData = NSData(base64EncodedString: strBase64, options: NSDataBase64DecodingOptions.IgnoreUnknownCharacters)!
print( dataDecoded)
Alamofire.request(.POST, "\(SERVERURL)fb_login", parameters: ["email": email,"fbid": fbID,"name": name ,"profile_pic": image,"user_type":"business" ]).responseJSON { response in
let json = JSON(data: response.data!)
if json["msg"].string == "User Details" {
let data = json["user_details"][0]
print(data)
LoginValue.sharedInstance.setUserLoginInfo(data)
self.reachNextViewController()
} else {
self.alertView("Sign Up Failed", message: json["error_description"].string!, button: "Close", destructive: false,secondButton: "")
}
print(json["error_description"])
}
}
error says
The profile pic must be a file of type: jpeg, jpg, png.

Cannot retrieve email from facebook using swift 3 and ios 10

Hello i am trying to retrieve my email from facebook as i am playing the facebook ios sdk using swift. IOS platform is 10, swift 3 and Xcode 8. I followed tutorials online but having trouble retrieving email.
below is my code:
if FBSDKAccessToken.current() == nil {
print("I got token")
let fbButton = FBSDKLoginButton()
fbButton.readPermissions = ["public_profile", "email", "user_friends"]
view.addSubview(fbButton)
fbButton.center = view.center
fbButton.delegate = self
self.fetchprofile()
}
else {
print("Dont have token")
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print(error.localizedDescription)
return
}
print("I'm in")
fetchprofile()
}
func fetchprofile() {
print("Getting profile")
let parameters = ["fields": "email"]
let graphRequest:FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: parameters, httpMethod: "GET")
graphRequest.start(completionHandler: {(connection, result, error) -> Void in
if error != nil {
print("Error retrieving details: \(error?.localizedDescription)")
return
}
guard let result = result as? [String:[AnyObject]], let email = result["email"] else {
return
}
print("Email: \(email)\n\n\n\n\n\n\n\n\n\n\n\n\n\n\n")
self.view.backgroundColor = UIColor.red
})
}
and in my appdelegate.swift file :
//have both google and facebook signin. Google works but facebook doesn't
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return GIDSignIn.sharedInstance().handle(url,
sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation]) ||
FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}
I am able to log in and log out but not able to retrieve email.
UPDATE Actually when i actually pass print(email) i can see it on the console as an optional statement. I'm having trouble displaying it without optional statment
I have solved the problem in this way:
func fetchProfile(){
FBSDKGraphRequest(graphPath: "/me", parameters: ["fields" : "email, name, id, gender"])
.start(completionHandler: { (connection, result, error) in
guard let result = result as? NSDictionary, let email = result["email"] as? String,
let user_name = result["name"] as? String,
let user_gender = result["gender"] as? String,
let user_id_fb = result["id"] as? String else {
return
}
})
}
This solution worked well for me without the "/" in the graphPath parameter!
FBSDKGraphRequest(graphPath: "me" .....