How to call arguments from Flutter in Swift native code?

4,878

You are passing a Map from Dart to native: {"isDebug": isDebug}, so you need extract the parameter from the map/dictionary at the Swift end.

  if let args = call.arguments as? Dictionary<String, Any>,
    let isDebug = args["isDebug"] as? Bool {
      // please check the "as" above  - wasn't able to test
      // handle the method

    result(nil)
  } else {
    result(FlutterError.init(code: "errorSetDebug", message: "data or format error", details: nil))
  }

Alternatively, just pass the boolean from the Dart end, without first putting it into a map.

_channel.invokeMethod('setDebugEnabled', isDebug);
Share:
4,878
Arnav
Author by

Arnav

Flutter developer

Updated on December 20, 2022

Comments

  • Arnav
    Arnav over 1 year

    I am trying to use PlatformViews in Flutter to show Swift code natively in my Flutter app, however my app is crashing with my current code.

    This is my AppDelegate currently where I am invoking my method channel:

    import Foundation
    
    @UIApplicationMain
    @objc class AppDelegate: FlutterAppDelegate, TJPlacementDelegate {
        var p = TJPlacement()
        override func application(
            _ application: UIApplication,
            didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
        ) -> Bool {
            let channelName = "NativeView"
            let rootViewController : FlutterViewController = window?.rootViewController as! FlutterViewController
            let methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: rootViewController as! FlutterBinaryMessenger)
            methodChannel.setMethodCallHandler {(call: FlutterMethodCall, result: FlutterResult) -> Void in
                if (call.method == "setDebugEnabled") {
                    let isDebug = call.arguments as! Bool
                    Tapjoy.setDebugEnabled(isDebug)
                } 
            }
            GeneratedPluginRegistrant.register(with: self)
            return super.application(application, didFinishLaunchingWithOptions: launchOptions)
        }
    }
    

    This is my Dart implementation for the native code:

     import 'package:flutter/material.dart';
     import 'tapjoy.dart';
    
        class Home extends StatefulWidget {
          @override
          _HomeState createState() => _HomeState();
        }
    
        class _HomeState extends State<Home> {
          @override
          void initState() {
            callTapjoy();
            super.initState();
          }
    
          Widget build(context) {
            return MaterialApp(
              home: Scaffold(
                appBar: AppBar(
                  title: Text('Test'),
                ),
                body: UiKitView(viewType: 'NativeView'),
              ),
            );
          }
    
          void callTapjoy() {
            Tapjoy.setDebugEnabled(true);
          }
        }
    
    //My code in tapjoy.dart
        class Tapjoy {
          static const MethodChannel _channel = const MethodChannel('NativeView');
              static void setDebugEnabled(bool isDebug) {
            _channel.invokeMethod('setDebugEnabled', {"isDebug": isDebug});
          } 
        } 
    

    My app crashes and shows me an error in the debug console:

    Could not cast value of type '__NSDictionaryM' (0x7fff87a61d78) to 'NSNumber' (0x7fff87b1eb08).
    2020-04-29 16:56:42.985269+0530 Runner[18484:224162] Could not cast value of type '__NSDictionaryM' (0x7fff87a61d78) to 'NSNumber' (0x7fff87b1eb08).
    

    enter image description here