2

I'm experimenting with adding TikTok authentication to my Flutter app (iOS only for now). My first intention was to utilize TikTok's Login Kit for this and I started to look at how to call native iOS code from Flutter.

I have managed to set up the necessary piping in order to call the iOS code from Flutter but it's when I want to respond with a result I'm having issues.

The TikTok auth flow is initiated fine, I get taken to my TikTok App on my phone where I can authenticate or cancel and finally get redirected back to my app. As a result of this, I'm expecting the completion closure to be called, where I can report back the response to Flutter. This does not seem to happen.

Here's my AppDelegate.swift

@UIApplicationMain
@objc class AppDelegate: FlutterAppDelegate {
    
    override func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {
        
        let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
        let channel = FlutterMethodChannel(name: "com.flutter.tiktok", binaryMessenger: controller as! FlutterBinaryMessenger)
        
        channel.setMethodCallHandler { (methodCall : FlutterMethodCall, result : @escaping FlutterResult) -> Void in
            if methodCall.method == "OpenTiktok"
            {
                let scopes = ["user.info.basic"]
                let scopesSet = NSOrderedSet(array:scopes)
                let request = TikTokOpenSDKAuthRequest()
                request.permissions = scopesSet
                request.state = "1234567890"
                
                request.send(controller, completion: { (resp : TikTokOpenSDKAuthResponse) -> Void in
                    result(resp.code ?? "NO_CODE") // <-- THIS DOES NOT HAPPEN
                })
            }
        }
        
        GeneratedPluginRegistrant.register(with: self)
        TikTokOpenSDKApplicationDelegate.sharedInstance().application(application, didFinishLaunchingWithOptions: launchOptions)
        
        return super.application(application, didFinishLaunchingWithOptions: launchOptions)
    }
    
    override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any] = [:]) -> Bool {
        guard let sourceApplication = options[UIApplication.OpenURLOptionsKey.sourceApplication] as? String,
              let annotation = options[UIApplication.OpenURLOptionsKey.annotation] else {
                  return false
              }
        
        if TikTokOpenSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: sourceApplication, annotation: annotation) {
            return true
        }
        return false
    }
    
    override func application(_ application: UIApplication, open url: URL, sourceApplication: String?, annotation: Any) -> Bool {
        if TikTokOpenSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: sourceApplication, annotation: annotation) {
            return true
        }
        return false
    }
    
    override func application(_ application: UIApplication, handleOpen url: URL) -> Bool {
        if TikTokOpenSDKApplicationDelegate.sharedInstance().application(application, open: url, sourceApplication: nil, annotation: "") {
            return true
        }
        return false
    }
}

And here's how I'm triggering the message from Flutter:

Future<void> openTiktok() async {
  try {
    var code = await platform.invokeMethod("OpenTiktok");
    setState(() {
      _code = code;
    });
  } catch (e) {
    print(e);
  }
}

Appreciate any kind of feedback, thanks!

1 Answers1

2

Got things to work finally and it had nothing to do with Flutter at all and was purely an iOS thing. Got some inspiration from this SO question.

What I had to do was to tweak the second application override. The options dictionary seems to always be empty which caused the false return.

This is the final version of that application override:

override func application(_ app: UIApplication, open url: URL, options: [UIApplication.OpenURLOptionsKey : Any]) -> Bool {
    if TikTokOpenSDKApplicationDelegate.sharedInstance().application(app, open: url, sourceApplication: nil, annotation: "") {
        return true
    }
    return super.application(app, open: url, options: options)
}

Thanks