How to implement a FlutterPlugin's method handler in Swift?

4,217

I've managed to figure it out by myself by reading some examples of Swift code calling Objective-C and inspecting the Objective-C sources.

Here's how I implemented it:

import Flutter
import UIKit
import Mobileapi

public class SwiftGohashMobilePlugin: NSObject, FlutterPlugin {
    public static func register(with registrar: FlutterPluginRegistrar) {
        let channel = FlutterMethodChannel(name: "gohash_mobile", binaryMessenger: registrar.messenger())
        let instance = SwiftGohashMobilePlugin()
        registrar.addMethodCallDelegate(instance, channel: channel)
    }

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult) {
        switch call.method {
        case "getDb":
            if let args = call.arguments as? [String] {
                if args.count == 2 {
                    var error : NSError?
                    let db = MobileapiReadDatabase(args[0], args[1], &error)
                    if let errorMessage = error?.userInfo.description {
                        result(FlutterError.init(code: "NATIVE_ERR",
                                                 message: "Error: " + errorMessage,
                                                 details: nil))
                    } else {
                        // SUCCESS!!
                        result(db!)
                    }
                } else {
                    result(FlutterError.init(code: "BAD_ARGS",
                                             message: "Wrong arg count (getDb expects 2 args): " + args.count.description,
                                             details: nil))
                }
            } else {
                result(FlutterError.init(code: "BAD_ARGS",
                                         message: "Wrong argument types",
                                         details: nil))
            }
        default:
            result(FlutterMethodNotImplemented)
        }
    }
}

Suggestions for improvements are welcome!

Share:
4,217
Renato
Author by

Renato

Software developer working at Twobo Technologies, Sweden. Java/Kotlin/Groovy/OSGi developer.

Updated on December 04, 2022

Comments

  • Renato
    Renato over 1 year

    I am trying to use Flutter to write a mobile app. Unfortunately, I need to implement a Flutter plugin to be able to call some native APIs.

    Objective-C is too alien for me, so I really prefer to use Swift (which I also don't know well but it's close enough to Kotlin that I feel familiar with it) to create the plugin.

    I got the plugin skeleton setup by Flutter, but now I am trying to implement the method handler function:

    public func handle(_ call: FlutterMethodCall, result: @escaping FlutterResult)
    

    The native function I am trying to use has this signature (generated with gomobile):

    FOUNDATION_EXPORT MobileapiDatabase* MobileapiReadDatabase(
      NSString* filePath, NSString* password, NSError** error);
    

    I don't understand several things though:

    1. how to return an error using the result object?
    2. how to report the method is not implemented?
    3. how to use the native function's error object?

    I can only find Objective-C examples, not a single Swift sample turned up by Googling around (the only sample I found didn't handle errors or anything else).

    This is what I've got so far:

    public func handle(_ call: FlutterMethodCall, 
        result: @escaping FlutterResult) {
      switch call.method {
      case "getDb":
        let args = call.arguments as! [String]
        if args.count == 2 {
            let error = NSError() // ERROR in next line
            MobileapiReadDatabase(args[0], args[1], error)
            // how to check if there was an error?
        }
        // TODO report wrong arguments
      default:
        // TODO report method not implemented
      }
    }
    

    Would really appreciate any help.