iOS change ViewController if user is not authed with Facebook (Swift) - ios

I have a tabbed Swift app (and new to app development) and I have the FB Core and Login kit.
If the user is logged in (FBSDKAccessToken.currentAccessToken() is not nil) then I'd like to display the view as normal. If they're not I'd like to display a login view with a button to authorize the app.
I know how to make the button, my question is what's the best place/way to interrupt the app and redirect to the login view. This should probably also do the check and redirect when coming back on to the app.
I saw this answer showing how you can interrupt and load a different view in func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?).
I suppose I should also check in func applicationDidBecomeActive(application: UIApplication)?
Facebook says to use the SDK as follows:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
// showLoginIfUnauthed() ??
return FBSDKApplicationDelegate.sharedInstance()
.application(application, didFinishLaunchingWithOptions: launchOptions)
}
// Overload when coming back from authenticating
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance()
.application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}
func applicationDidBecomeActive(application: UIApplication) {
// showLoginIfUnauthed() ??
FBSDKAppEvents.activateApp()
}
I was thinking of calling a method in these three functions, is this the wrong way of going about this?:
func showLoginIfUnauthed() {
if !FBSDKAccessToken.currentAccessToken() {
self.window = UIWindow(frame: UIScreen.mainScreen().bounds)
let mainStoryboard: UIStoryboard = UIStoryboard(name: "Main", bundle: nil)
var loginController: LoginViewController = mainStoryboard.instantiateViewControllerWithIdentifier("LoginController") as! LoginViewController
self.window?.rootViewController = loginController
self.window?.makeKeyAndVisible()
}
}
Thanks.

Related

3D Touch quick actions not working when called from didFinishLaunchingWithOptions

I'm implementing 3D touch quick actions in my app and I have the following problem:
When the app is already running and so the quick action is initiated through perform Action For Shortcut Item, it works perfectly fine. However, when the app is killed and then launched through a quick action (so didFinishLaunchingWithOptions) it does not take me to the desired view controller, but rather to the home screen of the app.
Here is my code:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
//... other stuff I'm doing
if let shortcutItem = launchOptions?[UIApplication.LaunchOptionsKey.shortcutItem] as? UIApplicationShortcutItem {
shortcutItemToProcess = shortcutItem
}
return true
NOTE: I've read previous SO answers where they said that I need to return false in didFinishLaunchingWithOptions when the app was launched through a quick action, so that performAction won't get called. I need to always return true however in my didFinishLaunching method because of the other things I'm handling there. I tried however to return false just to see if that causes the problem and the app still behaved the same way.
func application(_ application: UIApplication, performActionFor shortcutItem: UIApplicationShortcutItem, completionHandler: #escaping (Bool) -> Void) {
shortcutItemToProcess = shortcutItem
}
Here is how I present the view controller:
func applicationDidBecomeActive(_ application: UIApplication) {
if let shortcutItem = shortcutItemToProcess {
if shortcutItem.type == "com.myName.MyApp.myQuickAction" {
let storyboard = UIStoryboard(name: "Main", bundle: nil)
let myViewController = storyboard.instantiateViewController(withIdentifier: "myViewController") as! MyViewController
if let navVC = window?.rootViewController as! UINavigationController? {
navVC.pushViewController(myViewController, animated: true)
}
}
So this works fine when app is already running, but it lands me on the home page of my app when the app is killed. What am I doing wrong and how can I solve this?

Check if user is logged in to facebook and change viewcontroller

i have been trying the app to check if the user is already logged in or not to Facebook but i need to change the ViewController depending if the user is logged or not, here is what i got, im really confused:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
self.window!.rootViewController = LoginViewController()
self.window!.makeKeyAndVisible()
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
func application(application: UIApplication, openURL url: NSURL, sourceApplication: String?, annotation: AnyObject) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, open: url as URL?, sourceApplication: sourceApplication, annotation: annotation)
}
but, im getting an error message that says Use of unresolved identifier 'LoginViewController'
im really confused and i don't know if im near to achieve what i want.
Thanks.
P.D: this code is in the AppDelegate.swift file
This is not remotely related to Facebook or Firebase as your tag and title says.
LoginViewController class cannot be resolved in your projects scope. This is either your LoginViewController class is not available in your target. Or the actual file is not inside of your project.
Check this :
'Use of Unresolved Identifier' in Swift

FB Login using Swift 3 not returning any values and not get back the user to the App after successful login

I'm using iOS 10 Swift 3 to integrate FB Login. I have followed all steps from Facebook documentation. Now the issue is, after successful login it doesn't returning any values and not get back the user to the app.
Note: The same works perfectly in Swift 2.
Hi I raised this issue to facebook developer support and the issue is that I have not implemented the correct delegate methods for iOS10. and you can find the correct delegate implementation here
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)
}
}
Don't forget to set Keychain Sharing
project targets -> Capabilities -> Keychain Sharing -> Toggle Switch ON
you can follow this
http://ashishkakkad.com/2015/05/facebook-login-swift-language-ios/
for me the "FBSDKApplicationDelegate" doesn't work for the latest Facebook Swift SDK version v0.2.0
You can find my implementation for v0.2.2 here: https://gist.github.com/mbecker/bdbd28cd11394085c01cf442aaa42c72
//
// AppDelegate.swift
//
// Created by Mats Becker on 9/25/16.
// Copyright © 2016 safari.digital. All rights reserved.
//
import UIKit
import FacebookCore
#UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
var window: UIWindow?
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
return SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
}
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.
// Call the 'activate' method to log an app event for use
// in analytics and advertising reporting.
AppEventsLogger.activate(application)
}
func applicationWillTerminate(_ application: UIApplication) {
// Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return SDKApplicationDelegate.shared.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 SDKApplicationDelegate.shared.application(
application,
open: url as URL!,
sourceApplication: sourceApplication,
annotation: annotation
)
}
}
Evn: iOS 10, XCode 8.3.2, Swift 3, facebook-sdk-swift-0.2.0
Tested and worked.
Since above answers are indicated as deprecated code, I have changed the syntax.
https://gist.github.com/jgchoi/097b59d85d6b378a81925be93a62fef9
import UIKit
import FacebookCore
#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 SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return SDKApplicationDelegate.shared.application(app, open: url, options: options)
}
public func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return SDKApplicationDelegate.shared.application(application, open: url)
}
}
}
I have experienced the same problem with Facebook and Twitter integration.I have solved it as follows.
func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
let appname:String = options.first?.value as! String
print(appname)
if appname == "com.facebook.Facebook" {
return FBSDKApplicationDelegate.sharedInstance().application(
app,
open: url as URL!,
sourceApplication: options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String,
annotation: options[UIApplicationOpenURLOptionsKey.annotation]
)
}
return Twitter.sharedInstance().application(app, open: url, options: options)
}
public func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
return SDKApplicationDelegate.shared.application(app, open: url, options: options)
}
Add this in addition to what you have in AppDelegate
Somehow the below code didn't work for me
public func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
return SDKApplicationDelegate.shared.application(application, open: url)
}
So had to change it to
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
let options = [UIApplication.OpenURLOptionsKey.sourceApplication: sourceApplication as Any,
UIApplication.OpenURLOptionsKey.annotation: annotation]
return SDKApplicationDelegate.shared.application(application, open: url, options: options)
}

how can I integrate facebook login to my ios app when I already have google sign in in appDelegate.swift?

I'm writing an app and I want to let users to log in to it with either google or facebook accounts. I currently already implemented the google solution and now I want to include facebook, but I'm struggling with one thing.
In the fb sign in tutorial the author asks to prepare the method in AppDelegate.swift class:
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}
My problem is that I already have the function didFinishLaunchingWithOptions implemented with google sign in logic:
func application(application: UIApplication,
didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
var configureError: NSError?
GGLContext.sharedInstance().configureWithError(&configureError)
assert(configureError == nil, "Error configuring Google services: \(configureError)")
GIDSignIn.sharedInstance().delegate = self
if let currentUser = GIDSignIn.sharedInstance().currentUser {
print("user is signed in as "+GIDSignIn.sharedInstance().clientID)
let sb = UIStoryboard(name: "Main", bundle: nil)
if let tabBarVC = sb.instantiateViewControllerWithIdentifier("TabController") as? TabController {
window!.rootViewController = tabBarVC
}
} else {
print("user is NOT signed in")
let sb = UIStoryboard(name: "Main", bundle: nil)
if let tabBarVC = sb.instantiateViewControllerWithIdentifier("ViewController") as? ViewController {
window!.rootViewController = tabBarVC
}
}
return true
}
So what now? is there any way of connecting/merging those two methods together?
Thanks
Just add both facebook and google codes in the same function.
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
// Google sign in code
// ...
return true
}
The return value (true/false) does not really matter. See this topic for explanation.

FB SDK - safari doesn't dismiss

When user tries to auth in app using facebook, safari window doesnt disappear after user grants permissions inside it. Safari reloads page and remains blank, not dismissing and not returning user to app
My appDelegate methods are following
func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
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)
}
Where can be the problem ?

Resources