Stay safe using Third-party SDKs in Swift

Recently a LOT of apps crashed because a Facebook SDK bug.

– But why too much apps crashes because a SDK error?

The answer is easy, because the app depends of SDK. In your AppDelegate, you include the imports and all code of the Third-party SDKs.

The big question is: How can I remove this dependency without remove de SDK?

The answer is: Using Dependency Injection and Feature Flag.

If you don’t know what is Dependency Injection and how you can do it in Swift, see this article.

Feature Flag

Feature flag is no more than an IF! But this if contains a condition returned from a server-side configuration. The most famous feature flag is the Remote Config, from Firebase.

You can do it by yourself, create a table with 2 columns: KEY and VALUE. In the key, save the key of feature as “enable_facebook_sdk” and in the value, set a string like “false”.

You can use a location setup too, to test, I don’t recommend use only local feature flag, because if you need to change something, you’ll need send a new version of your app. To test, you can use a Settings manager, see this article.

Stop! Let’s code!

Ok, we, developers like to see code, a line of code means more than a lot of words.

The first step to use Facebook SDK is add this code to your AppDelegate:

import FBSDKLoginKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)

        return true
    }
}

When you put this code here, your app can crash easily! Let’s see how fix:

1. Create a Protocol

protocol FacebookWrapperProtocol {
    func start(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?)
}

2. IMPLEMEnt the protocol

class FacebookWrapper: FacebookWrapperProtocol {
    func start(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) {
        ApplicationDelegate.shared.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
}

3. USE IN YOU APPDELEGATE

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    facebookWrapper = FacebookWrapper()
    if isFacebookEnabled {
        facebookWrapper?.start(application: application, didFinishLaunchingWithOptions: launchOptions)
    }
}

Here I’m setting the class inside the method, this is only to you understand and can test.  The variable isFacebookEnabled will be your feature flag code. BUT, how improve this code?

We are using DI (Dependency Injection) than, this IF, isn’t in the right place, the if will control what dependency we will inject, or if you are using optionals in your variable, don’t inject.

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    facebookWrapper = FacebookWrapper()
    if isFacebookEnabled {
        facebookWrapper = FacebookWrapper()
    }
    
    facebookWrapper?.start(application: application, didFinishLaunchingWithOptions: launchOptions)
}

You can use the DMInject lib:

var facebookWrapper: FacebookWrapperProtocol?

func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
    
    DMInject.main.initialize(mapper: DMInjectionMapper())
    facebookWrapper << DMInject()
    
    facebookWrapper?.start(application: application, didFinishLaunchingWithOptions: launchOptions)
    
}

By the way, HOW you will implement the DI is how you like and the best alternative to your app. BUT the important is: use DI!

It can appears to much code, replication, because you will need create all calls in the protocol and the protocol implementation, but this is the price to stay safe and continue using 3rd party SDKs.

I hope this helps you, if you have questions of suggestions, comment here or call me in my social networks.