Facebook SDK delegate methods not firing - ios

I have a very simple setup:
//AppDelegate.swift
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
window = UIWindow(frame:UIScreen.main.bounds) //puts a rectange the same size of the screen
window?.rootViewController = MainController()
window?.makeKeyAndVisible() //make the window and keyboard available for window
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let handled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
return handled
}
.....
}
//Main Controller
import Foundation
import UIKit
import Alamofire
class MainController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
view.addSubview(SplashController().view)
Timer.scheduledTimer(timeInterval: 1.0, target: self, selector: #selector(changeView), userInfo: nil, repeats: false)
}
func changeView() {
let authController = Authenticate()
view.addSubview(authController.view)
}
}
//View Controller
import Foundation
import UIKit
import FacebookLogin
import FBSDKLoginKit
class Authenticate: UIViewController,FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let loginButton = FBSDKLoginButton()
loginButton.delegate = self
loginButton.center = view.center
view.addSubview(loginButton)
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("DID LOG OUT!!!")
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
print("Login Delegate callback")
if error != nil {
print(error)
return
}
print("successfully logged into facebook")
}
func loginButtonWillLogin(_ loginButton: FBSDKLoginButton!) -> Bool {
print("WILL LOGIN")
return true
}
}
Everything appears generally to work fine with the login process (I get the FB prompt, login, am brought back to the app, etc.)
However, the delegates methods NEVER fire. I never see "DID LOG OUT" or "Login Delegate Callback" or "successfully logged into facebook".
What am I missing?
Thanks in advance for help/suggestions.

Related

GID.sharedInstance().signIn() crashes app

I have read the google docs to seek for an answer, I also looked on some similar posts but none of these helped me solve my problem.
I am trying to set UIButton as the trigger for google sign in.
For some reason, it crushes.
I am of course adding the code I have written.
Thanks in advance!
I have tried everything around this issue written by StackOverflow.
import UIKit
import Firebase
import GoogleSignIn
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
FirebaseApp.configure()
return true
}
func applicationWillResignActive(_ application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and invalidate graphics rendering callbacks. Games should use this method to pause the game.
}
func applicationDidEnterBackground(_ application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(_ application: UIApplication) {
// Called as part of the transition from the background to the active state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(_ application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
#available(iOS 9.0, *)
func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
if(GIDSignIn.sharedInstance().handle(url,
sourceApplication: options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
annotation: options[UIApplication.OpenURLOptionsKey.annotation]))
{
return true;
}else if(url.absoluteString.contains("www.mydomain.com")){
print("incoming url \(url.absoluteString)")
return true
}
return false
}
// [START openurl]
#available(iOS 8.0, *)
func application(_ application: UIApplication,
open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
if (GIDSignIn.sharedInstance().handle(url,
sourceApplication: sourceApplication,
annotation: annotation))
{
return true;
}else if(url.absoluteString.contains("www.mydomain.com")){
print("incoming url \(url.absoluteString)")
return true
}
return false;
}
}
//
// LogInViewController.swift
// Flash Chat
//
// This is the view controller where users login
// Control–Command–Space bar to get emojes
import UIKit
import Firebase
import SVProgressHUD
import GoogleSignIn
class LogInViewController: UIViewController, GIDSignInUIDelegate, GIDSignInDelegate {
//Textfields pre-linked with IBOutlets
#IBOutlet var emailTextfield: UITextField!
#IBOutlet var passwordTextfield: UITextField!
#IBOutlet weak var loginButton: UIButton!
#IBOutlet weak var upperView: UIView!
#IBOutlet weak var warningLabel: UILabel!
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().delegate = self
roundCorners(button: loginButton)
let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
upperView.addGestureRecognizer(tapGesture)
}
func roundCorners(button: UIButton) {
button.layer.cornerRadius = 20
button.layer.borderWidth = 1
button.layer.borderColor = UIColor.white.cgColor
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
}
#IBAction func signInViaGooglePressed(_ sender: UIButton) {
GIDSignIn.sharedInstance()?.signIn()
}
func sign(_ signIn: GIDSignIn!, didSignInFor user: GIDGoogleUser!, withError error: Error!) {
//if any error stop and print the error
if error != nil{
print(error ?? "google error")
return
}
print("Succses")
//if success display the email on label
}
#IBAction func logInPressed(_ sender: AnyObject) {
SVProgressHUD.show()
if checkDetailsValidity(){
Auth.auth().signIn(withEmail: emailTextfield.text!, password: passwordTextfield.text!) { (user, error) in
if error != nil {
self.warningLabel.text = "Incorrect email or password"
SVProgressHUD.dismiss()
}
else {
SVProgressHUD.dismiss()
print("Successfuly logged in!")
self.performSegue(withIdentifier: "goToChat", sender: self)
}
}
}
}
func checkDetailsValidity() -> Bool {
if emailTextfield.text!.isEmpty {
warningLabel.text = "Email is mandatory field"
return false
}
else if !emailTextfield.text!.contains("#") || !emailTextfield.text!.contains("."){
warningLabel.text = "Email is illegal"
return false
}
return true
}
}
you must set the key of app to the delegate of GIDSingIn in the view didLoad do this
override func viewDidLoad() {
super.viewDidLoad()
GIDSignIn.sharedInstance().uiDelegate = self
GIDSignIn.sharedInstance().delegate = self
GIDSignIn.sharedInstance().clientID = "yourappkey.apps.googleusercontent.com"
GIDSignIn.sharedInstance().serverClientID = "yourappkey.apps.googleusercontent.com"
roundCorners(button: loginButton)
let tapGesture = UITapGestureRecognizer(target: view, action: #selector(UIView.endEditing))
upperView.addGestureRecognizer(tapGesture)
}
replacin youappkey for your real one. then use this function to present the login view.
func sign(_ signIn: GIDSignIn!,present viewController: UIViewController!) {
self.present(viewController, animated: true, completion: nil)
}
and this one to close the login window.
func sign(_ signIn: GIDSignIn!,dismiss viewController: UIViewController!) {
self.dismiss(animated: true, completion: nil)
}
Follow the steps to integrate GoogleSignIn https://developers.google.com/identity/sign-in/ios/sign-in?ver=swift
Also, https://www.youtube.com/watch?v=QmnI5c85sf0 visually helps setting up the sign in.
You might be missing the URL Schema to handle the sign in.

Segue won't trigger after logged into facebook using swift

So I have managed to set it up so the whole login system works. It closes out of the browser once logged in but does not advance to the next viewController.
This is my AppDelegate.swift:
import UIKit
import CoreData
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
public func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey : Any]? = nil) -> Bool {
// Override point for customization after application launch.
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
app,
open: url as URL!,
sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation]
)
}
public func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(
application,
open: url as URL!,
sourceApplication: sourceApplication,
annotation: annotation)
}
}
This is my ViewController.swift:
import UIKit
import FBSDKCoreKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
var fbLoginSuccess = false
override func viewDidLoad() {
if (FBSDKAccessToken.current() != nil && fbLoginSuccess == true)
{
print("Logged In...")
} else {
print("Not Logged In...")
}
let loginButton = FBSDKLoginButton()
loginButton.readPermissions = ["public_profile", "email"]
loginButton.center = self.view.center
loginButton.delegate = self
self.view.addSubview(loginButton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// Facebook Login.
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil
{
print(error)
} else if result.isCancelled {
// Handle
} else {
fbLoginSuccess = true
print("User logged in...")
self.performSegue(withIdentifier: "showNew", sender: self)
}
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("User logged out...")
}
}
I have a storyboard Identifier 'showNew' and I cannot figure out why it doesn't trigger.

how to go to the another viewcontroller after facebook login?

How to go to the another viewcontroller after facebook login? What should be done in Main.storyboard?
Here is my AppDelegate.swift
import UIKit
import FBSDKCoreKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String!, annotation: options[UIApplicationOpenURLOptionsKey.annotation])
}
func applicationDidBecomeActive(_ application: UIApplication) {
FBSDKAppEvents.activateApp()
}
}
Here is ViewController.swift
import UIKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
override func viewDidLoad() {
super.viewDidLoad()
let loginButton = FBSDKLoginButton()
loginButton.center = self.view.center
view.addSubview(loginButton)
}
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error != nil {
print("Something went wrong... \(error)" )
return
}
print("Successfully logged in!")
}
func loginButtonDidLogOut(_ loginButton: FBSDKLoginButton!) {
print("Successfully logged out!")
}
}
You're probably looking for something like this:
if(FBSDKAccessToken.currentAccessToken() != nil) {
let storyboard = UIStoryboard(name: "MyStoryboardName", bundle: nil)
let vc = storyboard.instantiateViewController(withIdentifier: "myViewController")
self.navigationController?.push(vc, animated: true)
}
What that snippet does, is check whether the user is logged in via Facebook (I assume you're using the SDK), and if they are, instantiate a VC from the storyboard, and push it with the Navigation Controller. Where you want to put that, whether you want to present the VC in a different way, etc..., is up to you, as the flow of your app will heavily inform it.
Try this in your ViewController.swift:
func loginButton(_ loginButton: FBSDKLoginButton!, didCompleteWith result: FBSDKLoginManagerLoginResult!, error: Error!) {
if error == nil && !result.isCancelled{
let storyboard = UIStoryboard(name: "Main", bundle: nil)
if let vc = storyboard.instantiateInitialViewController(){
self.present(vc, animated: true, completion: nil)
}
}
}

Calling segue with swift if user already logged in with facebook

I have been following this tutorial on how to make a facebook login with swift. http://letsbuildthatapp.com/2016/03/26/swift-facebook-login-sdk-and-getting-users-email/
But, when i dismiss the app by double clicking on home button and sliding up the application I see my login screen with one difference. Button's text has changed to logout.
What i want to do is automatically skipping that login page and performing this segue: self.performSegueWithIdentifier("redirectAfterLogin", sender: self)
I come across this article yet I couldn't fix the issue by myself and now I'm little bit confused.
How to check if user is logged in with FBSDKLoginKit in iOS?
Below you can see my AppDelegate.swift and LoginVC.swift files. How can I fix this?
AppDelegate.swift
import UIKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate, CNPPopupControllerDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// Override point for customization after application launch.
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
return true
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationWillResignActive(application: UIApplication) {
// Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
// Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
}
func applicationDidEnterBackground(application: UIApplication) {
// Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
// If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
}
func applicationWillEnterForeground(application: UIApplication) {
// Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
}
func applicationDidBecomeActive(application: UIApplication) {
// Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
}
func applicationWillTerminate(application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
}
LoginVC.swift
import UIKit
import KASlideShow
class LoginVC: UIViewController, KASlideShowDelegate, FBSDKLoginButtonDelegate {
let loginButton: FBSDKLoginButton = {
let button = FBSDKLoginButton()
button.readPermissions = ["email"]
return button
}()
override func viewDidLoad() {
super.viewDidLoad()
// do stuff here
view.addSubview(loginButton)
loginButton.center = view.center
loginButton.readPermissions = ["public_profile", "email", "user_friends"]
loginButton.delegate = self // Remember to set the delegate of the loginButton
if let token = FBSDKAccessToken.currentAccessToken() {
fetchProfile()
}
if FBSDKAccessToken.currentAccessToken() != nil {
print("1")
self.performSegueWithIdentifier("redirectAfterLogin", sender: self)
}
}
func fetchProfile(){
print("fetching profile..")
let params = ["fields": "email, first_name, last_name, picture.type(large)"]
FBSDKGraphRequest(graphPath: "me", parameters: params).startWithCompletionHandler{ (connection, result, var error) -> Void in
if error != nil {
print (error)
return
}
if let email = result["email"] as? String {
print(email)
NSUserDefaults.standardUserDefaults().setObject(email, forKey: "email")
}
if let first_name = result["first_name"] as? String {
print(first_name)
NSUserDefaults.standardUserDefaults().setObject(first_name, forKey: "first_name")
}
if let last_name = result["last_name"] as? String {
print(last_name)
NSUserDefaults.standardUserDefaults().setObject(last_name, forKey: "last_name")
}
if let picture = result["picture"] as? NSDictionary, data=picture["data"] as? NSDictionary, url=data["url"] as? String {
print(url)
NSUserDefaults.standardUserDefaults().setObject(url, forKey: "url")
}
NSUserDefaults.standardUserDefaults().synchronize()
print(result) // this prints whole FBSDKGraphRequest API response
}
}
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
print("login completed")
fetchProfile()
self.performSegueWithIdentifier("redirectAfterLogin", sender: self)
}
func loginButtonDidLogOut(loginButton: FBSDKLoginButton!) {
}
func loginButtonWillLogin(loginButton: FBSDKLoginButton!) -> Bool {
return true
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
What you'll need to do is in appDelegate on
application(application: UIApplication, didFinishLaunchingWithOptions launchOptions:
if let root = UIApplication.sharedApplication().windows[0].rootViewController as? UINavigationController {
if CONDITION {
root.viewControllers = [USER_HOMEPAGE]
} else {
root.viewControllers = [USER_LOGIN]
}
}

Facebook iOS Login Returns isCancelled as True Swift

I have been attempting to create a fb login in my application, the problem is that once logged in the isCancelled value of the FBSDKLoginManagerLoginResult in the didCompleteWithResults is true. I have seen other people get this error but their problem was with their AppDelegate.swift which I see no problem with mine.
Here is my ViewController.swift:
import UIKit
import FBSDKCoreKit
import FBSDKShareKit
import FBSDKLoginKit
class ViewController: UIViewController, FBSDKLoginButtonDelegate {
var loginbutton = FBSDKLoginButton()
override func viewDidLoad() {
super.viewDidLoad()
//facebook login
if(FBSDKAccessToken.currentAccessToken()==nil){
println("Not Logged In..")
}else{
println("Logged In")
}
loginbutton.readPermissions = ["public_profile","email","user_friends"]
loginbutton.center = CGPointMake(self.view.center.x, self.view.center.y+(self.view.frame.height/4))
self.loginbutton.delegate = self
FBSDKProfile.enableUpdatesOnAccessTokenChange(true)
self.view.addSubview(loginbutton)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
//Facebook Login
func loginButton(loginButton: FBSDKLoginButton!, didCompleteWithResult result: FBSDKLoginManagerLoginResult!, error: NSError!) {
if error==nil{
println("declined:\(result.declinedPermissions)")
println("granted:\(result.grantedPermissions)")
println("isCan:\(result.isCancelled)")
println("token:\(result.token)")
let accessToken = FBSDKAccessToken.currentAccessToken()
}else{
println(error.localizedDescription)
}
}
Here is my AppDelegate.swift:
import UIKit
import FBSDKCoreKit
import FBSDKShareKit
import FBSDKLoginKit
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(application:UIApplication, openURL url:NSURL, sourceApplicaiton:String?, annotation:AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplicaiton, annotation: annotation)
}
func applicationDidBecomeActive(application: UIApplication) {
FBSDKAppEvents.activateApp()
}

Resources