Doesn't call Facebook loginButton didCompleteWithResult - ios

I followed the tutorial here to integrate Facebook login on my application. I can login successfully with that button, but it doesn't call my method didCompleteWithResult upon login to fetch user details. This is my code.
import UIKit
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
#IBOutlet weak var loginBtn: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func configureFacebook()
{
loginBtn.readPermissions = ["public_profile", "email", "user_friends"];
loginBtn.delegate = self
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
FBSDKGraphRequest.init(graphPath: "me", parameters: ["fields":"first_name, last_name, picture.type(large)"]).startWithCompletionHandler { (connection, result, error) -> Void in
let strFirstName: String = (result.objectForKey("first_name") as? String)!
let strLastName: String = (result.objectForKey("last_name") as? String)!
let strPictureURL: String = (result.objectForKey("picture")?.objectForKey("data")?.objectForKey("url") as? String)!
print("Welcome, \(strFirstName) \(strLastName)")
//self.profilePic.image = UIImage(data: NSData(contentsOfURL: NSURL(string: strPictureURL)!)!)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{
}
}

Option-1
I dont know where you add this method in here I submit answer in dynamically , customize your self..
override func viewDidLoad() {
super.viewDidLoad()
configureFacebook() // if you want here add here or else if you want to load the facebook details in Button action add there
// Do any additional setup after loading the view.
}
func configureFacebook()
{
loginBtn.readPermissions = ["public_profile", "email", "user_friends"];
loginBtn.delegate = self
}
option-2
if you add the delegate in directly in your viewcontroller do like for example

Related

App crashes with Firebase Phone Auth

I hope that this question is not duplicate because I couldn't find any thing similar.
I have two view controllers:
NEWPhoneAuthViewController
NEWVerifyCodeViewController
NEWPhoneAuthViewController Code:
import UIKit
import Firebase
class NEWPhoneAuthViewController: UIViewController {
#IBOutlet weak var phoneTxtField: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func submitPressed(_ sender: Any) {
let phoneNumber = phoneTxtField.text!
PhoneAuthProvider.provider().verifyPhoneNumber(phoneNumber, uiDelegate: nil, completion: { (verificationID, error) in
if let error = error {
debugPrint(error.localizedDescription)
return
}
guard let verificationID = verificationID else { return }
print("Verification ID")
print(verificationID)
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
self.performSegue(withIdentifier: "toCodefromPhoneAuth", sender: nil)
//self.navigationController?.pushViewController(verifyScene, animated: true)
})
}
}
and my NEWVerifyCodeViewController code is:
import UIKit
import Firebase
class NEWVerifyCodeViewController: UIViewController {
#IBOutlet weak var codeTxtField: UITextField!
var verificationID:String?
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func verifyPressed(_ sender: Any) {
if let verificationCode = codeTxtField.text {
let credential = PhoneAuthProvider.provider().credential(withVerificationID: verificationID!, verificationCode: verificationCode)
Auth.auth().signIn(with: credential) { (user, error) in
if let error = error {
debugPrint(error.localizedDescription)
}else {
debugPrint("Verified successfully")
print("Navigating to SignUp")
//self.performSegue(withIdentifier: "toSignUpfromCode", sender: nil)
//let newSignUp = NEWSignUp()
//self.navigationController?.pushViewController(newSignUp, animated: true)
//self.performSegue(withIdentifier: "toSignUpFromPhone", sender: nil)
//Once you have verified your phone number kill the firebase session.
//try? Auth.auth().signOut()
}
}
}
}
}
Now the problem is: when I tap on verify button in NEWVerifyCodeViewController the App crashes,
NOTES:
I printed Verification ID and its not NULL.
I printed code that the user receives and its not NULL.
So I'm not sure why that happens, and my console doesn't show any error after the tap except these:
So I made a small tweak that made my project work.
I changed this part in NEWPhoneAuthViewController :
let verifyScene = NEWVerifyCodeViewController()
verifyScene.verificationID = verificationID
to:
first created a global variable called: gVerificationID and set it to:
gVerificationID = verificationID
Thats it, not sure if thats the best practice and not sure why the first code didn't work but this is how I fixed it.

Changing ViewController if user is Facebook Logged in

I'm having quite some troubles implementing Facebook login in my iOS , everything works fine if the user is not already logged in, the application fetches correctly the data from Facebook and pass them to the next ViewController , instead if is already logged in it should automatically segue to a recap page that shows user's info but i can't make it happen, currently I'm using this method :
override func viewDidLoad() {
super.viewDidLoad()
LoginButton.delegate = self
if (FBSDKAccessToken.currentAccessToken() != nil) {
self.performSegueWithIdentifier("Login", sender: self)
}
}
but in the console i get :
Facebook_Login.LoginViewController: 0x7fc04a519ca0 on Facebook_Login.ViewController: 0x7fc04a41c1e0 whose view is not in the window hierarchy!
i've also tried using the viewdidAppear method, but it segues to the recap page without updating the variables so i get an empty page
here' the complete code:
View Controller 1
import UIKit
import FBSDKLoginKit
class ViewController: UIViewController,FBSDKLoginButtonDelegate {
var nome1:String = ""
var cognome1:String = ""
var email1:String = ""
var compleanno:String = ""
var città:String = ""
var genere:String = ""
var immagine_url:String = ""
#IBOutlet weak var LoginButton: FBSDKLoginButton!
#IBAction func LoginAction(sender: AnyObject) {
LoginButton.delegate = self
LoginButton.readPermissions = ["email"]
}
func FetchInfo(){
print("scarico le informazioni...")
let parametri = ["fields":"email, first_name, last_name, birthday, hometown, gender, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: parametri).startWithCompletionHandler{(connection,result,error) -> Void in
if (error != nil){
print ("errore")
return
}
else {
if let email = result["email"] as? String {
print(email)
self.email1 = email
}
if let nome = result["first_name"] as? String {
print(nome)
self.nome1 = nome
}
if let cognome = result["last_name"] as? String {
print(cognome)
self.cognome1 = cognome
}
if let compleanno = result["birthday"] as? String{
print(compleanno)
}
if let città = result["hometown"] as? String{
print(città)
}
if var genere = result["gender"] as? String{
if (genere == "male"){
genere = "maschio"
}
else {
genere = "femmina"
}
print(genere)
}
}
if let picture = result["picture"] as? NSDictionary, data = picture["data"] as? NSDictionary, url = data["url"] as? String{
self.immagine_url = url
print(self.immagine_url)
}
}
return
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
if (result.isCancelled == true){
print("cancellato")
}
else {
print("login effettuato")
FetchInfo()
self.performSegueWithIdentifier("Login", sender: self)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!){
}
func loginButtonWillLogin(loginButton: FBSDKLoginButton!) -> Bool{
return true
}
#IBAction func returned(segue:UIStoryboardSegue){
}
override func viewDidLoad() {
super.viewDidLoad()
LoginButton.delegate = self
}
override func viewDidAppear(animated: Bool) {
if (FBSDKAccessToken.currentAccessToken() != nil) {
FetchInfo()
if(nome1 == ""){
}
else {
self.performSegueWithIdentifier("Login", sender: self)
}
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
let destinazione:LoginViewController = segue.destinationViewController
as! LoginViewController
destinazione.temp_nome = nome1
destinazione.temp_cognome = cognome1
destinazione.temp_email = email1
destinazione.img_profile_url = immagine_url
}
}
ViewController 2:
import UIKit
import FBSDKLoginKit
class LoginViewController: UIViewController, FBSDKLoginButtonDelegate {
var temp_nome = ""
var temp_cognome = ""
var temp_email = ""
var img_profile_url:String = ""
#IBOutlet weak var Nome_Utente: UILabel!
#IBOutlet weak var email: UILabel!
#IBOutlet weak var Immagine_Utente: UIImageView!
#IBOutlet weak var Login_button: FBSDKLoginButton!
#IBAction func Login_button_Action(sender: AnyObject) {
Login_button.delegate = self
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!){
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!){
self.performSegueWithIdentifier("Back", sender: self)
}
override func viewDidLoad() {
super.viewDidLoad()
Nome_Utente.text = "\(temp_nome)" + " " + "\(temp_cognome)"
email.text = "\(temp_email)"
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
First of all, avoid to reset your LoginButton.delegate in the LoginAction() function.
If the user is already logged in, to avoid an useless call to the Facebook Graph API (if you do not necessarily need to update his informations), you can store your user informations in CoreData or in a NSUserDefault.
If you never used it you can use the CDHelper lib (CoreDataHelper) which will allow you to use it without difficulties.
Hope I was helpful, if not, do not hesitate to give us a feedback.
Btw, in your viewDidAppear(animated: Bool) function, you have to call super.viewDidAppear(animated) !

Swift IOS Facebook Login Fast-App-Switch

Im a swift beginner and have already implemented FB login for IOS. I was wondering how to do it with Fast-App-Switching and staying on the App without moving to Facebook login form.
Heres my code for the ViewController.swift handling FB Login:
import UIKit
import Foundation
class FacebookLoginViewController : UIViewController, FBSDKLoginButtonDelegate {
let loginButton: FBSDKLoginButton = {
let button = FBSDKLoginButton()
button.readPermissions = ["public_profile","email","user_friends"]
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(loginButton)
loginButton.center = view.center
loginButton.delegate = self
if let token = FBSDKAccessToken.currentAccessToken() {
fetchProfile()
}
}
func fetchProfile() {
print("User Profile fetched")
redirectToHome()
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
print("User has successfully logged on.")
redirectToHome()
}
func redirectToHome() {
let storyboard:UIStoryboard = UIStoryboard(name:"Main", bundle: nil)
let homeFeed: UIViewController = storyboard.instantiateViewControllerWithIdentifier("homeFeed") as UIViewController
self.presentViewController(homeFeed, animated: true, completion: nil)
}
func loginButtonWillLogin(loginButton: FBSDKLoginButton!) -> Bool {
return true
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
print("User has logged out")
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
As far as I knew and since I saw your question did further research, it is still not possible to skip the second screen. By second screen I mean a webpage where you must tap "log in" and it provides details about how the app will interact with Facebook. Even the app for this website takes you there when logging in with Facebook. If it this changes or I am mistaken I will update this post. Since I just joined the site I cannot post pictures yet:) but I hope we are talking about the same thing.

Facebook Login for Swift with facebook iOS SDK 4.9.1

I got trouble with facebook iOS SDK 4.9.1 on integrating facebook login using swift. and main trouble is unable to find any guideline regarding it for swift.
http://www.brianjcoleman.com/tutorial-how-to-use-login-in-facebook-sdk-4-0-for-swift/
http://swiftdeveloperblog.com/facebook-sdk-ios-login-example-with-swift/
IOS Swift and Facebook SDK
I try to implement below but it doesn't work at all.
class ViewController: UIViewController {
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
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
This is for viewcontroller :
import FBSDKLoginKit
class ViewController: UIViewController,FBSDKLoginButtonDelegate {
#IBOutlet weak var fbLoginView: FBSDKLoginButton!
override func viewDidLoad() {
super.viewDidLoad()
if(FBSDKAccessToken.currentAccessToken() == nil){
print("Not Logged ")
}
else{
print("Logged In")
}
fbLoginView.readPermissions = ["public_profile","email","user_birthday"]
fbLoginView.delegate = self
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!)
{
if error == nil
{
print("login complete")
let request = FBSDKGraphRequest(graphPath:"me", parameters:["fields":"name,gender,birthday,first_name,last_name,email"])
request.startWithCompletionHandler
{
(connection, result, error) in
if error != nil
{
print ("error \(error)")
}
else if let userData = result as? NSDictionary
{
var frstname = userData["first_name"] as? String
var lastname = userData["last_name"] as? String
var gender = userData["gender"] as? String
var birthday = userData["birthday"] as? String
var email = userData["email"] as? String
print(result)
}
}
}
else
{
print(error.localizedDescription)
}
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{
print("user logged out")
}
}
In App Delegate override the following method as :
func application(application: UIApplication,openURL url: NSURL, sourceApplication: String?,annotation: AnyObject) -> Bool
{
return FBSDKApplicationDelegate.sharedInstance().application(application,openURL: url,sourceApplication: sourceApplication,annotation: annotation)
}
Swift 5+
In App Delegate override the following method as :
func application(application: UIApplication,openURL url: NSURL, sourceApplication: String?,annotation: AnyObject) -> Bool
{
return ApplicationDelegate.sharedInstance().application(application,openURL: url,sourceApplication: sourceApplication,annotation: annotation)
}

Facebook SDK swift: problems with fetching user data (segue)

It does not seem like my data is passed to the new view controller.
Indeed, it only works in the (first) view controller once logged in.
I believe there are a few mistakes in my work.
Please tell me where I'm wrong, I am a beginner so please be precise and efficient. Thanks a lot.
class ViewController: UIViewController, FBSDKLoginButtonDelegate
{
override func viewDidLoad()
{
super.viewDidLoad()
if FBSDKAccessToken.currentAccessToken() != nil {
//user already has access token
self.logUserData()
} else {
loginButton.readPermissions = ["public_profile", "email", "user_friends"]
loginButton.delegate = self
self.Photo.image = UIImage(named: "Why subtle bckd image1")
self.Photo2.image = UIImage(named: "Un combo unique pict")
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// MARK: PR/VAR
var firstName: String!
var lastName: String!
var email: String!
#IBOutlet var loginButton: FBSDKLoginButton!
#IBAction func loginButtonsend(sender: UIButton) {
sender.setTitle("firstName", forState: UIControlState.Normal)
sender.setTitle("lastName", forState: UIControlState.Normal)
sender.setTitle("email", forState: UIControlState.Normal)
}
#IBOutlet var Photo: UIImageView!
#IBOutlet var Photo2: UIImageView!
// MARK: FACEBOOK LOGIN
override func viewWillAppear(animated: Bool) {
self.logUserData()
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!)
{ if error == nil {
let fbAccessToken = FBSDKAccessToken.currentAccessToken().tokenString
println("Logged in")
} else { println(error.localizedDescription) } }
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!)
{
println("User logged out.")
}
func logUserData()
{
let graphRequest = FBSDKGraphRequest(graphPath: "me?fields=id,email,first_name,last_name", parameters: ["fields": "first_name,email,last_name"])
graphRequest.startWithCompletionHandler { (connection, result, error) -> Void in
if error != nil
{
// Process error
println(error)
}
else
{
println(result.grantedPermissions)
println("fetched user = \(result)")
var firstName = result.valueForKey("first_name")
println("firstName = \(firstName)")
var lastName = result.valueForKey("last_name")
println("lastName is = \(lastName)")
var email = result.valueForKey("email")
println("email is = \(email)")
self.performSegueWithIdentifier("showNew", sender: self)
}
}
}
// SEGUE:
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject?) {
if (segue.identifier == "showNew") {
if let destinationVC = segue.destinationViewController as? NewViewController {
destinationVC.firstName = firstName
destinationVC.lastName = lastName
destinationVC.email = email
}
}
}
}
And in my new view controller I have the following:
class NewViewController: UIViewController {
var firstName: String!
var lastName: String!
var email: String!
#IBOutlet var firstNameLabel: UILabel!
#IBOutlet var lastNameLabel: UILabel!
#IBOutlet var emailLabel: UILabel!
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
if (firstName != nil) {
firstNameLabel.text = firstName
}
if (lastName != nil) {
lastNameLabel.text = lastName
}
if (email != nil) {
emailLabel.text = email
}
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
#IBAction func logoutButtonTapped(sender: AnyObject) {
let loginManager = FBSDKLoginManager ()
loginManager.logOut()
let loginPage = self.storyboard?.instantiateViewControllerWithIdentifier("ViewController") as ViewController
//?
let loginPageNav = UINavigationController (rootViewController: loginPage)
let appDelegate = UIApplication.sharedApplication().delegate as AppDelegate
appDelegate.window?.rootViewController = loginPageNav
}
/*
// MARK: - Navigation
// In a storyboard-based application, you will often want to do a little preparation before navigation
override func prepareForSegue(segue: UIStoryboardSegue!, sender: AnyObject!) {
// Get the new view controller using segue.destinationViewController.
// Pass the selected object to the new view controller.
}
*/
}
It seems like you're never setting the variables from your ViewController, but instead are creating three which have the same name as the ones you should be using on logUserData. Just change to:
println(result.grantedPermissions)
println("fetched user = \(result)")
firstName = result.valueForKey("first_name")
println("firstName = \(firstName)")
lastName = result.valueForKey("last_name")
println("lastName is = \(lastName)")
email = result.valueForKey("email")
println("email is = \(email)")

Resources