I want to upload the profile picture from Facebook to Firebase. I tried this answer: Upload Facebook image URL to Firebase Storage
However, Swift is giving me errors on the third line of code of that answer. The code is:
let dictionary = result as? NSDictionary
let data = dictionary?.object(forKey: "data")
let urlPic = (data?.objectForKey("url"))! as! String
Swift is telling me: Cannot call value of non-function type 'Any?!' after I changed the code to what Swift keeps suggesting me:
let urlPic = ((data as AnyObject).object(ForKey: "url"))! as! String
What is the code to use when I want to retrieve the profile picture from Facebook? My goal is to also store it into Firebase, but that will come after I get the profile picture first.
The answer is in Swift 1.2
I took reference here and implemented also
You can do this:
// accessToken is your Facebook id
func returnUserProfileImage(accessToken: NSString)
{
var userID = accessToken as NSString
var facebookProfileUrl = NSURL(string: "http://graph.facebook.com/\(userID)/picture?type=large")
if let data = NSData(contentsOfURL: facebookProfileUrl!) {
imageProfile.image = UIImage(data: data)
}
}
This is the way I got Facebook id:
func returnUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else
{
println("fetched user: \(result)")
if let id: NSString = result.valueForKey("id") as? NSString {
println("ID is: \(id)")
self.returnUserProfileImage(id)
} else {
println("ID es null")
}
}
})
}
Related
I've been trying to follow Facebooks documentation exactly but can't understand why my code doesn't work, even though it is exactly as in the docs. I am already signing into Facebook on my app, but I need to get the profile data.
Here is my function.
func fetchFacebookUser() {
let connection = GraphRequestConnection()
connection.add(GraphRequest(graphPath: "/me")) { httpResponse, result in
switch result {
case .success(let response):
print("Graph Request Succeeded: \(response)")
case .failed(let error):
print("Graph Request Failed: \(error)")
}
}
connection.start()
}
You'll notice it is exactly like the documentation:
https://developers.facebook.com/docs/swift/graph
But I can't even build the project because I get this error in Xcode:
Contextual closure type '(GraphRequestConnection?, Any?, Error?) -> Void' expects 3 arguments, but 2 were used in closure body
Insert ',<#arg#> '
It has the 'Fix' button but that just breaks the whole thing and Xcode (red warning) complains that none of the cases in the switch statement exist.
I have searched everywhere, the closest solution I got was this SO post: Facebook GraphRequest for Swift 5 and Facebook SDK 5
But that had no answers :(
I'm sure someone has called the Graph API using Swift? What am I missing here?
However i implement facebook login my app which works fine.
On button click I called facebook login using LoginManager.
#IBAction func continueWithFacebook(_ sender: Any) {
let fbLoginManager : LoginManager = LoginManager()
fbLoginManager.logIn(permissions: ["email"], from: self) { (result, error) -> Void in
if (error == nil){
let fbloginresult : LoginManagerLoginResult = result!
if (result?.isCancelled)!{
return
}
if(fbloginresult.grantedPermissions.contains("email")) {
self.getFBUserData()
}
}
}
}
After that I get the data of user using GraphAP
func getFBUserData() {
if((AccessToken.current) != nil){
GraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
guard let userDict = result as? [String:Any] else {
return
}
if let picture = userDict["picture"] as? [String:Any] ,
let imgData = picture["data"] as? [String:Any] ,
let imgUrl = imgData["url"] as? String {
self.uURLString = imgUrl
/*let url = URL(string: imgUrl)*/
print(imgData)
}
if let n = userDict["name"] as? String {
self.name = n
}
if let e = userDict["email"] as? String {
self.email = e
}
self.socialLogIn()
}
})
}
}
Add in your pod file -
pod 'FBSDKCoreKit' and
pod 'FBSDKLoginKit'
Try using like this you will get your derided result.
Happy Coding
For a little background - I have a 'Follow Facebook Friends' ViewController where users can view their friends who also have downloaded my app to follow on the app.
I have correctly called the FBSDK to get a list of friends that have also downloaded the app, but now I need to get these friends uid's in Firebase so I can follow/unfollow them accordingly.
Currently, when I get a FB users id - I get the numeric string as mentioned in the facebook documentation. However, the users uid in Firebase is different. Is there a way to find which firebase user correlates with a FB id? Or should I try to store a Facebook User by facebook id in firebase?
var facebookContacts = [User]()
func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
let cell = tableView.dequeueReusableCell(withIdentifier: "facebookContactCell", for: indexPath) as! FacebookContactCell
// Configure the cell...
let user = facebookContacts[indexPath.row]
cell.contactNameLabel.text = user.name
cell.userId = user.documentId
// Set follow button state
if followingArray.contains(cell.userId) {
cell.followButton.isSelected = true
} else {
cell.followButton.isSelected = false
}
let userImageRef = storage.child("userImages/"+(user.documentId)+"/profile_pic.jpg")
// Download in memory with a maximum allowed size of 1MB (1 * 1024 * 1024 bytes)
userImageRef.getData(maxSize: 1 * 1024 * 1024) { (data, error) in
if let error = error {
// Uh-oh, an error occurred! Display Default image
print("Error - unable to download image: \(error)")
cell.contactImageView.image = UIImage(named: "userProfileGray")
} else {
// Data for "locationImages/(locationId).jpg" is returned
cell.contactImageView.image = UIImage(data: data!)
}
SVProgressHUD.dismiss()
}
return cell
}
func getFbFriends() {
let params = ["fields": "id, first_name, last_name, name, email, picture"]
let graphRequest = FBSDKGraphRequest(graphPath: "/me/friends", parameters: params)
let connection = FBSDKGraphRequestConnection()
connection.add(graphRequest, completionHandler: { (connection, result, error) in
if error == nil {
let resultdict = result as! NSDictionary
print("Result Dict: \(resultdict)")
let data : NSArray = resultdict.object(forKey: "data") as! NSArray
for i in 0..<data.count {
let valueDict : NSDictionary = data[i] as! NSDictionary
let id = valueDict.object(forKey: "id") as! String
print("the id value is \(id)")
let name = valueDict.object(forKey: "name") as! String
print("the name value is \(name)")
let picDict = valueDict["picture"] as! NSDictionary
let picData = picDict["data"] as! NSDictionary
let picURL = picData.object(forKey: "url") as! String
print("the url value is \(picURL)")
self.facebookContacts.append(User(name: name, documentId: id))
}
DispatchQueue.main.async {
self.tableView.reloadData()
}
let friends = resultdict.object(forKey: "data") as! NSArray
print("Found \(friends.count) friends")
} else {
print("Error Getting Friends \(String(describing: error))");
}
})
connection.start()
}
I do not think that you can get the UID of your user based on their Facebook ID. It seems that you have two possibilities:
Search by email. This should allow you to pinpoint the person you are looking for.
Implement custom Facebook authentication. It requires a little extra work but is not too difficult to do.
The FBSDKGraphRequest connection handler used in the SignUpViewController of a tutorial app is now outdated. I updated it to a point where it won't error until I try to place the Parse code after the user successfully signs up. Once I put in the Parse code (to sign the user up using the FB SDK results), I get the errors "Type of expression is ambiguous without more context".
Here's what I have so far:
let graphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, gender, email"])
graphRequest.startWithCompletionHandler ({ connection, result, error in
if error != nil {
//onError()
print(error)
return
} else {
let fbResult = result as! Dictionary<String, AnyObject>
print("FbResult \(fbResult)")
PFUser.currentUser()?["gender"] = result["gender"]
PFUser.currentUser()?["name"] = result["name"]
try PFUser.currentUser()?.save()
let userId = result["id"] as! String
let facebookProfilePictureUrl = "https://graph.facebook.com/" + userId + "/picture?type=large"
if let fbpicUrl = NSURL(string: facebookProfilePictureUrl) {
if let data = NSData(contentsOfURL: fbpicUrl) {
self.profilePic.image = UIImage(data: data)
let imageFile:PFFile = PFFile(data: data)!
PFUser.currentUser()?["image"] = imageFile
try PFUser.currentUser()?.save()
}
})
For some reason XCode hates anything after the "print fbresult" line. Here's a pastebin of the working code before the Parse code:
http://pastebin.com/dUyEvYmr
How can I update this to accept the Parse code?
Thanks!!
PS: I can confirm that I have the latest Parse and FB SDK. I'm running the latest version of XCode (7.2.1).
I came across with the same problem when going through the udemy swift class too.
My solution was:
if let fbResult = {
...
let name : NSString = (fbResult.valueForKey("name") as? NSString)!
let gender : NSString = (fbResult.valueForKey("gender") as? NSString)!
...
}
Hope it works for you!
I'm trying to pull the username and profile picture for my apps profile page. I'm using Parse and the Facebook SDK.
I have a UILabel and a UIView connected as outlets.
When I try to set the profileImageView, it gives me the error "Value of type 'UIImageView' has no member 'setImageWithURL'" Is this an upgrade with Swift?
Here is my code...
func setProfilePicture() {
FBSDKGraphRequest(graphPath: "me", parameters: nil).startWithCompletionHandler({ (connection, result, error) -> Void in
if let dict = result as? Dictionary<String, AnyObject> {
let name: String = dict["name"] as! String
let facebookID: String = dict["id"] as! String
let pictureUrl = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
self.profileImageView.setImageWithURL(NSURL(string: pictureUrl)!)
self.nameLabel.text = name
PFUser.currentUser()!.setValue(name, forKey: "name")
PFUser.currentUser()!.saveInBackground()
}
})
}
if let url = NSURL(string: "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1") {
if let data = NSData(contentsOfURL: url){
self.profileImageView.contentMode = UIViewContentMode.ScaleAspectFit
self.profileImageView.image = UIImage(data: data)
}
}
Try creating a function, fbProfilePicURL, that takes a Facebook ID and returns the profile picture URL as an NSURL, then change
self.profileImageView.setImageWithURL(NSURL(string: pictureUrl)!)
to
self.profileImageView.setImageWithURL(NSURL.fbProfilePicURL(facebookID))
Not 100% sure on this, but let me know if it works.
I'm using FB Login, and my app is crashing every now and then within that method. It works fine for me, but not for some other users. In this function, I'm setting user data in Parse with data received from the FBSDKGraphRequest.
// Sends FB Graph Request and sets user attributes in Parse
func setUserData() {
var user = PFUser.currentUser()!
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
println("Set user values error: \(error)")
}
else
{
firstName = result.valueForKey("first_name") as! NSString
lastName = result.valueForKey("last_name") as! NSString
user["name"] = "\(firstName) \(lastName)"
NSUserDefaults.standardUserDefaults().setObject("\(firstName) \(lastName)", forKey: "name")
id = result.valueForKey("id") as! NSString
user["fbID"] = id
gender = result.valueForKey("gender") as! NSString
user["gender"] = gender
email = result.valueForKey("email") as! NSString
user["email"] = email
user["score"] = 100
user.saveInBackgroundWithBlock({ (success, error) -> Void in
if success {
objID = user.objectId!
}
})
self.performSegueWithIdentifier("segue", sender: self)
}
})
}
Now, in Crashlytics, I'm getting EXC_BREAKPOINT, but can't figure out exactly where the crash is coming from or what to do about it. Looks like it may be coming from Facebook's side? Any help would be appreciated.
I've had the same issue. I forgot to put the permissions on the FBSDKLoginButton:
facebookLoginButton.readPermissions = ["public_profile", "email", "user_friends"];
Maybe you forgot it too?