Which View Controller Should I Pass in My Swift Native Code for a Flutter Plugin

Which view controller should I pass in my Swift native code for a Flutter plugin?

Try this:

if let vc = UIApplication.shared.delegate?.window??.rootViewController  as? FlutterViewController {
interstitial.show(withPresenting: vc)
}

How to call arguments from Flutter in Swift native code?

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);

How can I push a UIViewController from FlutterViewController

You need to embed FlutterViewController in container UINavigationController programmatically or in storyboard, then you will be able to push your next controller.

Here is example how to embed programmatically:

@interface AppDelegate()
@property (nonatomic, strong) UINavigationController *navigationController;
@end

@implementation AppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
[GeneratedPluginRegistrant registerWithRegistry:self];

UIViewController *flutterViewController = [[FlutterViewController alloc] init];
self.navigationController = [[UINavigationController alloc] initWithRootViewController:flutterViewController];
[self.navigationController setNavigationBarHidden:YES];

self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
self.window.rootViewController = self.navigationController;
[self.window makeKeyAndVisible];

return true;
}

- (void)pushExample {
UIViewController *viewController = [[UIViewController alloc] init];
[self.navigationController pushViewController:viewController animated:true];
}

@end

When needed(e.g. button tapped) invoke pushExample.
Also you can check "storyboard" way in this video

Flutter plugin - MethodChannel: .invokeMethod() from native iOS to Flutter never reaches Flutter part

So, the reason of described behavior itself (in my particular case) was definitely in changing root view controller from FlutterViewController to my custom iOS UIViewController (reason - plugin had a reference to native SDK which used its own storyboard).

Seems there wasn't any feature request yet to clarify that inconvenience for native iOS plugin users in documentation/readme.

UPD: there is an issue which describes possible reasons of merely expected behaviour: https://github.com/flutter/flutter/issues/52456

Flutter - How to invoke channel in native Swift code?

Define the method channel in the AppDelegate:

var methodChannel: FlutterMethodChannel!

Initialize it:

override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
) -> Bool {
...

methodChannel = FlutterMethodChannel(name: channelName, binaryMessenger: rootViewController as! FlutterBinaryMessenger)

}

Now you can call invokeMethod:

public func requestDidSucceed(_ placement: TJPlacement!) {
methodChannel.invokeMethod()
}

How to stream data from swift to flutter using event channel?

just call mEventSink as a function

mEventSink(data)

Use FlutterEndOfEventStream constant to signal end of stream

mEventSink(FlutterEndOfEventStream)

if you going to send error to flutter side use

mEventSink(FlutterError(code: "ERROR_CODE",
message: "Detailed message",
details: nil))

Reference to API DOC

Complete swift example

let eventChannel = FlutterEventChannel(name: "your.channel.id", binaryMessenger: messenger!)                                                                            
eventChannel.setStreamHandler(SwiftStreamHandler())

....

class SwiftStreamHandler: NSObject, FlutterStreamHandler {
public func onListen(withArguments arguments: Any?, eventSink events: @escaping FlutterEventSink) -> FlutterError? {
events(true) // any generic type or more compex dictionary of [String:Any]
events(FlutterError(code: "ERROR_CODE",
message: "Detailed message",
details: nil)) // in case of errors
events(FlutterEndOfEventStream) // when stream is over
return nil
}

public func onCancel(withArguments arguments: Any?) -> FlutterError? {
return nil
}
}


Related Topics



Leave a reply



Submit