Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

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

Tags:

swift

flutter

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.

like image 636
Renato Avatar asked Apr 28 '18 16:04

Renato


1 Answers

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!

like image 133
Renato Avatar answered Nov 15 '22 07:11

Renato