Integration new facebook SDK by swift

Today i tried to integrate facebook SDK to my Swift app but in the quick start on facebook guide page looks a bit different than my old code. How can i convert OBJ-C code below to swift?

- (void)applicationDidBecomeActive:(UIApplication *)application {
  [FBSDKAppEvents activateApp];
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                    didFinishLaunchingWithOptions:launchOptions];
}

- (BOOL)application:(UIApplication *)application
            openURL:(NSURL *)url
  sourceApplication:(NSString *)sourceApplication
         annotation:(id)annotation {
  return [[FBSDKApplicationDelegate sharedInstance] application:application
                                                         openURL:url
                                               sourceApplication:sourceApplication
                                                      annotation:annotation];
}

Thanks!

Answers


It's pretty much the same, except instead of using brackets, you use dots.

func applicationDidBecomeActive(application: UIApplication!) {
    FBSDKAppEvents.activateApp()
}

func application(application: UIApplication!, didFinishLaunchingWithOptions launchOptions: NSDictionary!) -> Bool {
    return FBSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
}

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String, annotation: AnyObject?) -> Bool {
    return FBSDKApplicationDelegate.sharedInstance().application(application, openURL: url, sourceApplication: sourceApplication, annotation: annotation)
}

Swift 3 with Swift FacebookSDK

Podfile
pod 'FacebookCore'
pod 'FacebookLogin'
info.plist

no changes from old sdk

<key>CFBundleURLTypes</key>
<array>
    <dict>
        <key>CFBundleURLSchemes</key>
        <array>
            <string>fb$(YOUR_FB_APP_ID)</string>
        </array>
    </dict>
</array>
<key>LSApplicationQueriesSchemes</key>
<array>
    <string>fbapi</string>
    <string>fb-messenger-api</string>
    <string>fbauth2</string>
    <string>fbshareextension</string>
</array>
<key>FacebookAppID</key>
<string>$(YOUR_FB_APP_ID)</string>
<key>FacebookDisplayName</key>
<string>$(YOUR_APP_NAME)</string>
AppDelegate.swift
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
    SDKApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
    ...
}

func applicationDidBecomeActive(_ application: UIApplication) {
    AppEventsLogger.activate(application)
}

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    let appId = SDKSettings.appId
    if url.scheme != nil && url.scheme!.hasPrefix("fb\(appId)") && url.host ==  "authorize" { // facebook
        return SDKApplicationDelegate.shared.application(app, open: url, options: options)
    }
    return false
}

...
LoginManager (custom login, see docs for default/button implementation)

contains custom code but you get the point

let facebookManager = LoginManager(loginBehavior: .systemAccount, defaultAudience: .everyone)
func loginWithFacebook() {
    self.facebookManager.logIn(HAAccountManager.shared.facebookPermissions, viewController: self) { (result) in
        switch result {
        case .failed(let error):
            self.showAlert(forError: error as NSError)
        case .cancelled:
            print("FB login cancelled")
        case .success(let grantedPermissions, let deniedPermissions, let accessToken):
            if grantedPermissions.contains(Permission(name: "email")) == true {
                ApiClient.shared.facebookSignIn(authToken: accessToken.authenticationToken, completion: { (err, user) in
                    if err == nil {
                        // success
                    }
                    else {
                        self.showAlert(forError: err!)
                    }
                })
            }
            else {
                self.showAlert(forError: HAError(title: String(format: String.somethingError, String.signIn), message: grantedPermissions.contains(Permission(name: "email")) == true ? String.noAccountFound : String.missingEmailForSignUp))
            }
        }
    }
}
Analytics
// custom ex
AppEventsLogger.log(AppEvent(name: "open_app", parameters: ["logged_in": NSNumber(value: HAAccountManager.shared.isUserLoggedIn())], valueToSum: nil))

// purchase ex
AppEventsLogger.log(
    AppEvent.purchased(
        amount: Double(revenue),
        currency: currency,
        extraParameters: [
            AppEventParameterName.contentId : orderId,
            AppEventParameterName.itemCount : order.orderItems.count.nsNumber()
        ])
)

This has been depricated in iOS 10.

func application(application: UIApplication, openURL url: NSURL, sourceApplication: String, annotation: AnyObject?) -> Bool {

For Swift 3.0, you can use:

Swift 3.0

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    let isHandled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[.sourceApplication] as! String!, annotation: options[.annotation])
    return isHandled
}

I know this is a pretty old question here but it seams that it will never be outdated as Facebook hasn't updated their QuickStart guide for a long time.

So here is the solution for Swift 4.x.

In didFinishLaunching:

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {

    FBSDKApplicationDelegate.sharedInstance()?.application(application, didFinishLaunchingWithOptions: launchOptions)

    return true
}

In open Url:

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {

    let handled = FBSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: options[.sourceApplication] as? String, annotation: options[.annotation])
    return handled
}

In iOS 9 i use:

func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool
{   
    FBSDKApplicationDelegate.sharedInstance().application(app, openURL: url, sourceApplication: options["UIApplicationOpenURLOptionsSourceApplicationKey"] as! String, annotation: options["UIApplicationOpenURLOptionsAnnotationKey"])
    return true
}

On iOS 9 you should be using:

func application(application: UIApplication,openURL url: NSURL, options: [String: AnyObject]) -> Bool {
   return ApplicationDelegate.shared.application(application, openURL: url, sourceApplication: options[UIApplicationOpenURLOptionsSourceApplicationKey] as? String, annotation: annotation: options[UIApplicationOpenURLOptionsAnnotationKey])
}

I found the potential for the Application delegate to break in iOS 9 with the annotation: options[UIApplicationOpenURLOptionsAnnotationKey] as it will not accept nil values. You can set this to a blank string and the application should run fine with facebook after this.

Swift 2.2 docs:

You specify optional chaining by placing a question mark (?) after the optional value on which you wish to call a property, method or subscript if the optional is non-nil. This is very similar to placing an exclamation mark (!) after an optional value to force the unwrapping of its value. The main difference is that optional chaining fails gracefully when the optional is nil, whereas forced unwrapping triggers a runtime error when the optional is nil.


In swift 3.0.1

return GIDSignIn.sharedInstance().handle(url, sourceApplication:    
options[UIApplicationOpenURLOptionsKey.sourceApplication] as! String, annotation:     
options[UIApplicationOpenURLOptionsKey.annotation])

Since I want to support iOS 8, I have modified the function application(_:open:options:) in Whitney Foster's answer to

func application(_ app: UIApplication, open url: URL, options: [UIApplicationOpenURLOptionsKey : Any] = [:]) -> Bool {
    let appId = SDKSettings.appId
    if url.scheme != nil && url.scheme!.hasPrefix("fb\(appId)") && url.host ==  "authorize" { // facebook
        if #available(iOS 9.0, *) {
            return SDKApplicationDelegate.shared.application(app, open: url, options: options)
        }
    }
    return false
}

and implemented additional fallback function

// Fallback on earlier versions
func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
    return SDKApplicationDelegate.shared.application(application, open: url, sourceApplication: sourceApplication, annotation: annotation)
}

if let fbSDKAppId = FBSDKSettings.appID(),
            url.scheme!.hasPrefix("fb\(fbSDKAppId)"),
            url.host == "authorize" { // facebook
            return FBSDKApplicationDelegate.sharedInstance().application(application,
                                                                         open: url,
                                                                         sourceApplication: sourceApplication,
                                                                         annotation: annotation)
}

For swift 5 with latest FBSDK (FBSDKCoreKit 5.2.1)

func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        let handled = ApplicationDelegate.shared.application(app, open: url, options: options)

        return handled
    }

Need Your Help

How to dispatch on main queue synchronously without a deadlock?

objective-c ios objective-c-blocks grand-central-dispatch

I need to dispatch a block on the main queue, synchronously. I don’t know if I’m currently running on the main thread or no. The naive solution looks like this:

iPhone / iOS : Presenting HTML 5 Keyboard for Postal Codes

ios iphone html5 input keyboard

There are several tricks for displaying different keyboards on mobile devices for HTML 5 inputs (i.e. &lt;input&gt; tags).