Where is the latest Facebook Swift Documentation. I can't get the FB Login Dialog to show up. The call to loginWithReadPermissions never returns?
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController {override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
let loginManager = FBSDKLoginManager()
loginManager.logInWithReadPermissions(["basic_info", "email", "user_likes"], fromViewController: self.parentViewController, handler: { (result, error) -> Void in
if error != nil {
print(FBSDKAccessToken.currentAccessToken())
} else if result.isCancelled {
print("Cancelled")
} else {
print("LoggedIn")
}
})
}
You code should work if you exclude "user_likes" from permissions.
From facebook docs:
If your app asks for more than public_profile, email and user_friends, Facebook must review it before you release it. Learn more about the review process and what's required to pass review.
https://developers.facebook.com/docs/facebook-login/permissions/v2.5#reference-user_likes
Another problem may be that you have not set correctly the FacebookSDK in your project. See this tutorial: https://developers.facebook.com/docs/ios/getting-started/
So the answer is to use FBSDKLoginButton with the following
In the class declaration of the viewController
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate
Then show the FBLogin Button with
// Setup the FB Login/Logout Button FB will take care of the
// verbiage based on the current access token
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
// If we have an access token, then let's display some info
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// Display current FB premissions
print (FBSDKAccessToken.currentAccessToken().permissions)
// Since we already logged in we can display the user datea and taggable friend data.
self.showUserData()
self.showFriendData()
}
Show the users info with
func showUserData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: ["fields" : "id, name, gender, first_name, last_name, locale, email"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
print("Error: \(error)")
}
else
{
let userName : NSString = result.valueForKey("name") as! NSString
print("User Name is: \(userName)")
if let userEmail : NSString = result.valueForKey("email") as? NSString {
print("User Email is: \(userEmail)")
}
}
})
}
And to display the taggable friends
func showFriendData()
{
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me/taggable_friends?limit=999", parameters: ["fields" : "name"])
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
print("Error: \(error)")
}
else
{
if let friends : NSArray = result.valueForKey("data") as? NSArray{
var i = 1
for obj in friends {
if let name = obj["name"] as? String {
print("\(i) " + name)
i++
}
}
}
}
})
}
Related
I am stuck after coding the Facebook login.....!
After the login procedure I just end up with a logout button.
I would like to make use of the App Invites for iOS but I cant figure out how to integrate it...
The documentations on "Facebook.developer" is hard to understand.
This is my code so far in the view controller:
import UIKit
import FacebookLogin
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
var dict : [String : AnyObject]!
override func viewDidLoad() {
super.viewDidLoad()
//creating button
let loginButton = LoginButton(readPermissions: [ .publicProfile, .userFriends, .email ])
loginButton.center = view.center
//adding it to view
view.addSubview(loginButton)
//if the user is already logged in
if let accessToken = FBSDKAccessToken.current(){
getFBUserData()
}
}
//when login button clicked
#objc func loginButtonClicked() {
let loginManager = LoginManager()
loginManager.logIn([ .publicProfile, .userFriends, .email ], viewController: self) { loginResult in
switch loginResult {
case .failed(let error):
print(error)
case .cancelled:
print("User cancelled login.")
case .success(let grantedPermissions, let declinedPermissions, let accessToken):
self.getFBUserData()
}
}
}
//function is fetching the user data
func getFBUserData(){
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
self.dict = result as! [String : AnyObject]
print(result!)
print(self.dict)
}
})
}
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
/*
Check for successful login and act accordingly.
Perform your segue to another UIViewController here.
*/
let viewController = self.storyboard?.instantiateInitialViewController("StoryBoardID") as? UITableViewController
self.presentViewController(viewController, animated: true, completion: nil)
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
// Actions for when the user logged out goes here
}
}
Any help?
I am trying to customize the Facebook login button after following this guide. Everything is integrated correctly, I can login to Facebook, and logout without a hitch.
Now my next goal is to make the screen look like my mock up, this includes placing the login button correctly on the storyboard, but the only issue is that it doesn't show up on the story board, it just appears when I run the simulation. I looked at other overflow answers, but they weren't really helpful as they were geared towards earlier versions of swift / Xcode, and didn't work from what the comments said. My code is exactly the same as the guide, as this is the first screen that I am trying to implement.
Help would be much appreciated.
If you want to use the custom facebook SDK button you can create any custom button in the storyboard and provide action in the viewcontroller like this
Import at top
import FBSDKCoreKit
import FBSDKLoginKit
Swift 3:
#IBAction func loginFacebookAction(sender: AnyObject) {//action of the custom button in the storyboard
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["email"], from: self) { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result!
// if user cancel the login
if (result?.isCancelled)!{
return
}
if(fbloginresult.grantedPermissions.contains("email"))
{
self.getFBUserData()
}
}
}
}
func getFBUserData(){
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
//everything works print the user data
print(result)
}
})
}
}
Older Swift version:
#IBAction func loginFacebookAction(sender: AnyObject) {//action of the custom button in the storyboard
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logInWithReadPermissions(["email"], fromViewController: self) { (result, error) -> Void in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result
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){
//everything works print the user data
print(result)
}
})
}
}
If you want default facebook login button you can take UIView and set Class* field of the Custom Class** section in the Identity Inspector, we must set the FBLoginValue
Ref: Default SDK login button tutorial:http://www.appcoda.com/ios-programming-facebook-login-sdk/
Ref: Custom SDK login button for parameters and more info:https://developers.facebook.com/docs/facebook-login/ios
POD INSTALL
source 'https://github.com/CocoaPods/Specs.git'
use_frameworks!
target “ProjectName” do
pod 'FacebookCore'
pod 'FacebookLogin'
pod 'FacebookShare'
end
AppDelegate.swift
import FacebookLogin
import FBSDKLoginKit
import FacebookCore
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}
ViewController.swift
import UIKit
import FacebookLogin
import FBSDKLoginKit
import FacebookCore
class ViewController: UIViewController {
override func viewDidLoad() {
if(FBSDKAccessToken.current() == nil){
print("Not logged in ")
}else{
print("Logged in already")
getFacebookUserInfo()
}
}
#IBAction func CustomButton_Click(_ sender: Any) {
getFacebookUserInfo()
}
func getFacebookUserInfo(){
let loginManager = LoginManager()
loginManager.logIn([.publicProfile, .email ], viewController: self) { (result) in
switch result{
case .cancelled:
print("Cancel button click")
case .success:
let params = ["fields" : "id, name, first_name, last_name, picture.type(large), email "]
let graphRequest = FBSDKGraphRequest.init(graphPath: "/me", parameters: params)
let Connection = FBSDKGraphRequestConnection()
Connection.add(graphRequest) { (Connection, result, error) in
let info = result as! [String : AnyObject]
print(info["name"] as! String)
}
Connection.start()
default:
print("??")
}
}
}
}
Info.plist
Info.plist --> right click ->OpenAs -->Source Code --> add < dict > .. < /dict >
<key>CFBundleURLTypes</key>
<array>
<dict>
<key>CFBundleURLSchemes</key>
<array>
<string>YOUR APP ID</string>
</array>
</dict>
</array>
<key>FacebookAppID</key>
<string>YOUR APP ID</string>
<key>FacebookDisplayName</key>
<string>YOUR APP NAME</string>
#IBAction func buttonLogin(_ sender: Any) {
let fbLoginManager : FBSDKLoginManager = FBSDKLoginManager()
fbLoginManager.logIn(withReadPermissions: ["public_profile","email"], from: self) { (result, error) in
if (error == nil){
let fbloginresult : FBSDKLoginManagerLoginResult = result!
if fbloginresult.grantedPermissions != nil {
if(fbloginresult.grantedPermissions.contains("email")) {
if((FBSDKAccessToken.current()) != nil){
FBSDKGraphRequest(graphPath: "me", parameters: ["fields": "id, name, first_name, last_name, picture.type(large), email"]).start(completionHandler: { (connection, result, error) -> Void in
if (error == nil){
let dict: NSDictionary = result as! NSDictionary
if let token = FBSDKAccessToken.current().tokenString {
print("tocken: \(token)")
let userDefult = UserDefaults.standard
userDefult.setValue(token, forKey: "access_tocken")
userDefult.synchronize()
}
if let user : NSString = dict.object(forKey:"name") as! NSString? {
print("user: \(user)")
}
if let id : NSString = dict.object(forKey:"id") as? NSString {
print("id: \(id)")
}
if let email : NSString = (result! as AnyObject).value(forKey: "email") as? NSString {
print("email: \(email)")
}
}
})
}
}
}
}
}
}
Welcome to StackOverflow, Shika! That tutorial shows you how to add the button that Facebook provides as part of their SDK. The tutorial tells you centers the button in the center of the device's screen. Facebook allows you to create your own button, if you'd like to. In my opinion, I like it better, because you can play with it in the storyboard, unlike the button created programmatically in Swift. You can use the Facebook docs here and scroll down to "Custom Login Button". Your code will change, but not by much! If you choose to go this route, make sure to delete the code you copied and pasted to add the button located in viewDidLoad. Also, you can delete the FBSDKLoginButtonDelegate you added at the top of the Swift file.
my name is Vincent and I need your help !
(My code is not exhaustive)
No problem to login or logout with the Facebook SDK ... BUT
When I start my app, no access token and when i click on the Login button, it prints me an accessToken, then I logout.
How to get the accessToken when the app starts ?
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class HomeViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
getUserStatuts()
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
// MARK -> Facebook Connect
func loginToFacebook() {
if let fbToken = FBSDKAccessToken.currentAccessToken() {
print("Acces token : \(fbToken)")
loginManager.logOut()
print("Logout")
} else {
print("Login")
loginManager.logInWithPublishPermissions(publishPermissions, fromViewController: nil, handler: {
(result:FBSDKLoginManagerLoginResult!, error:NSError!) -> Void in
if error == nil {
self.getUserData()
} else {
print(error.localizedDescription)
}
})
}
}
func getUserData() {
let readPermissions = ["public_profile", "email", "user_friends", "user_birthday"]
let parameters = ["fields": "id, first_name, last_name, name, birthday, picture.type(large)"]
let request = FBSDKGraphRequest(graphPath: "me", parameters: parameters)
request.startWithCompletionHandler({
(connection, result, error) -> Void in
if error == nil {
// display info
}
})
}
In the login function you want to implement the
let fbLogin = FBSDKLoginManager()
fblogin.logout()
the fblogin.logout() must be implemented before fbLogin.logInWithReadPermissions(["email"], fromViewController: self) { (facebookResult, facebookError) in
if facebookError != nil { ` to clear any access tokens from previous login.
I'm trying to make a facebook login for my app to connect with facebook, everything went good, I created a login page added an imageView to show the user facebook's profile photo, a label to display the name of the user, I managed to display the image of the user when I loged in to Facebook, but I couldn't connect the name's label to the code to display the user name! can anybody help please ? This is my code :
import UIKit
import FBSDKCoreKit
import FBSDKShareKit
import FBSDKLoginKit
class ViewController: UIViewController,FBSDKLoginButtonDelegate {
#IBOutlet weak var nameLabel: UILabel!
#IBOutlet weak var profileImageView: FBSDKProfilePictureView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// User is already logged in, do work such as go to next view controller.
}
else
{
let loginView : FBSDKLoginButton = FBSDKLoginButton()
self.view.addSubview(loginView)
loginView.center = self.view.center
loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
}
// Facebook Delegate Methods
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")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
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)")
let userName : NSString = result.valueForKey("name") as! NSString
println("User Name is: \(userName)")
let userEmail : NSString = result.valueForKey("email") as! NSString
println("User Email is: \(userEmail)")
}
})
}
}
If you go through the code in the debugger, is userName getting set to the user's name? I don't see anywhere in your code where you're actually setting the UILabel nameLabel's text to your userName var.
Could you provide some more detail? If this was simply an oversight, the problem is you need to set nameLabel's text to userName.
nameLabel.text = userName
If this wasn't an oversight and userName is not getting set to the proper value of the user's name, you're most likely doing something incorrectly in the Facebook SDK.
not sure if you figured this out yet, but I was having the same problem I had the profile pic displaying but not the username. Anywho I just added the last line 'self.' to your code and it worked:
let userName : NSString = result.valueForKey("name") as! NSString
print("Username is: \(userName)")
self.nameResult.text = userName as String
swap 'nameResult' for your labels name 'nameLabel' and that should work.
I've been frustratingly trying to implement Parse's Facebook login function into my app using Swift for over a month and can't seem to figure it out. I successfully linked my app to both Facebook and Parse separately, but I can't make a Parse user using Facebook's login. I believe the AppDelegate is setup correctly, so I will only show my LoginViewController and hopefully someone who knows what they're doing can please help me out:
import UIKit
import Parse
import FBSDKCoreKit
import FBSDKLoginKit
protocol LoginViewControllerDelegate {
func onRegister(loginViewController : LoginViewController)
func onFacebookLogin(loginViewController : LoginViewController)
func onLogin(loginViewController : LoginViewController)
}
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
//MARK: - Outlets
#IBOutlet weak var lblStatus: UILabel!
//var delegate : LoginViewControllerDelegate?
// Set permissions required from the facebook user account
let permissions = [ "user_about_me", "user_relationships", "user_location", "user_birthday", "public_profile", "user_friends", "user_email", "user_gender"]
//MARK: - Initial Load
override func viewDidLoad() {
super.viewDidLoad()
self.lblStatus.alpha = 0
//Facebook
if (FBSDKAccessToken.currentAccessToken() != nil)
{
// User is already logged in, do work such as go to next view controller.
}
else
{
let loginView : FBSDKLoginButton = FBSDKLoginButton()
// self.view.addSubview(loginView)
// loginView.center = self.view.center
// loginView.readPermissions = ["public_profile", "email", "user_friends"]
loginView.delegate = self
}
// ---------------------------- Check if user is logged in ---------------------
if PFUser.currentUser() != nil {
println("parse: User already logged in")
performSegueWithIdentifier("loggedIn", sender: self)
}
}
//MARK: - Facebook Login Button
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if ((error) != nil) {
println(error) // 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
}
}
returnUserData()
}
#IBAction func facebookLoginDidPress(sender: AnyObject) {
self.lblStatus.alpha = 0
PFFacebookUtils.logInInBackgroundWithReadPermissions(self.permissions, block: {
(user: PFUser?, error: NSError?) -> Void in
if (user == nil) {
if (error == nil) {
println("User cancelled FB login")
self.lblStatus.alpha = 1
}else{
println("FB login error: \(error)")
self.lblStatus.alpha = 1
}
} else if user!.isNew {
println("User signed up and logged in with Facebook! \(user)")
self.requestFacebook()
self.returnUserData()
self.performSegueWithIdentifier("loggedIn", sender: self)
} else {
println("User logged in via Facebook \(user)")
self.performSegueWithIdentifier("loggedIn", sender: self)
}
})
}
func requestFacebook() {
let graphRequest : FBSDKGraphRequest = FBSDKGraphRequest(graphPath: "me", parameters: nil)
graphRequest.startWithCompletionHandler({ (connection, result, error) -> Void in
if ((error) != nil)
{
// Process error
println("Error: \(error)")
}
else if error == nil
{
var userData: NSDictionary = NSDictionary(objectsAndKeys: result)
var facebookID: AnyObject? = userData["id"]
var name: AnyObject? = userData["first_name"]
var gender: AnyObject? = userData["gender"]
var birthday: AnyObject? = userData["birthday"]
var pictureURL = "https://graph.facebook.com/\(facebookID)/picture?type=large&return_ssl_resources=1"
var URLRequest = NSURL(string: pictureURL)
var URLRequestNeeded = NSURLRequest(URL: URLRequest!)
NSURLConnection.sendAsynchronousRequest(URLRequestNeeded, queue: NSOperationQueue.mainQueue(), completionHandler: {(response: NSURLResponse!,data: NSData!, error: NSError!) -> Void in
if error == nil {
var picture = PFFile(data: data)
PFUser.currentUser()!.setObject(picture, forKey: "profilePicture")
PFUser.currentUser()!.saveInBackground()
}
else {
println("Error: \(error.localizedDescription)")
}
})
}
})
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
println("User Logged Out")
}
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
{
if let userName : NSString = result.valueForKey("name") as? NSString {
println("User Name is: \(userName)")
} else {println("No username fetched")}
if let userEmail : NSString = result.valueForKey("email") as? NSString {
println("User Email is: \(userEmail)")
} else {println("No email address fetched")}
if let userGender : NSString = result.valueForKey("gender") as? NSString {
println("User Gender is: \(userGender)")
} else {println("No gender fetched") }
}
})
}
}
Some important notes to make:
I am using the newest version of Parse (1.7.4) and FBSDK (4.1), so most other methods I've found online do not work anymore because certain functions or members have been removed since then.
The "func loginButton" is what I used for the FBSDKLoginButton, while the "#IBAction func facebookLoginDidPres" is for a regular UIButton I tried using for logging in. Based on what I've learned recently, I believe the UIButton method is the one I should go with, but that one leads to a Thread 1: Signal SIGABRT error stating:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[PFFacebookUtils logInInBackgroundWithReadPermissions:block:]: unrecognized selector sent to class 0x10ed3ed80'
*** First throw call stack:
...
libc++abi.dylib: terminating with uncaught exception of type NSException
(lldb) ""
So I placed an exception breakpoint and it ended at the end of the "logInInBackgroundWithReadPermissions" function in my IBAction with the console stating:
"[PFFacebookUtils logInInBackgroundWithReadPermissions:block:]: unrecognized selector sent to class 0x10dbe2db0 (lldb)"
The last detail I feel is worth mentioning is that my console states "parse: User already logged in" in when I run the app, however there is no User created when I check Parse. This is getting printed from the section under "check if the user is logged in" section of my LogInViewController's viewDidLoad function.
I will be forever grateful to anyone who can help me figure out this problem that's been puzzling me for far too long. Thank you in advance!
I deleted the old PFFacebookUtils Framework, but kept the PFFacebookUtilsV4 Framework, and that solved the problem for me! Hopefully that helps anyone else with this problem :)
I have the same problem, my solution is to define Login behaviour = Web
PFFacebookUtils.facebookLoginManager().loginBehavior = FBSDKLoginBehavior.Web
When I call this before call loginInBackground..., after clicking to the "OK" button, my application received call-back with a user (not nil) and PFUser.currentUser is updated with that user.