我怎样才能推动"来自FlutterViewController的UIViewController

时间:2017-08-12 02:09:16

标签: ios uiviewcontroller flutter

我想"推"在我们的Flutter视图中新的原生视图(在Android中的活动和在iOS中的UIViewController),在完成/完成新的原生视图后,make屏幕将返回到我们的Flutter视图。

我可以在Android中执行此操作。 但是,当我尝试在ios/Runner/AppDelegate.m中执行此操作时,我对iOS非常陌生:

  SwiftViewController *swiftViewController = [controller.storyboard instantiateViewControllerWithIdentifier:@"SwiftViewController"];
  [(FlutterViewController *)self.window.rootViewController pushViewController:swiftViewController animated:YES];

它给出错误:

  

" FlutterViewController"没有可见的@interface;声明了选择器' pushViewController:animated'

那么如何在iOS中做到这一点?感谢

更新

问题解决后,您可以找到我的示例代码here

4 个答案:

答案 0 :(得分:3)

pushViewController仅在您的控制器属于navigation stack时才有效,即如果您的FlutterViewController嵌入UINavigationController,那么您可以push另一个控制器就像这样:

    self.navigationController?.pushViewController(swiftViewController, animated: true)

第二个选项是:如果FlutterViewController中没有嵌入UINavigationController,您只需present另一个控制器就可以了:

    self.present(swiftViewController, animated: true, completion: nil)

答案 1 :(得分:3)

在Swift中,我们可以使用方法通道通过flutter action事件打开本机iOS viewController,

  • 扑朔迷离,您需要添加以下几行来触发本机iOS方法。将这些行添加到您的操作方法中
var platform = const MethodChannel('com.nativeActivity/iosChannel');
final String result = await platform.invokeMethod('StartNativeIOS');
  • 在iOS 中,在AppDelegate应用程序方法中添加以下几行
let controller : FlutterViewController = window?.rootViewController as! FlutterViewController

let methodChannel = FlutterMethodChannel(name: "com.nativeActivity/iosChannel", binaryMessenger:controller.binaryMessenger)

methodChannel.setMethodCallHandler({
  (call: FlutterMethodCall, result: @escaping FlutterResult) -> Void in
        
  if call.method == "StartNativeIOS" {
    let mainVC = MainViewController() // Your viewController
    let navigationController = UINavigationController(rootViewController: mainVC)
    self.window.rootViewController = navigationController
    self.window.makeKeyAndVisible()
  } else {
    result(FlutterMethodNotImplemented)
    return
  }
})

它将起作用!欢呼

注意:,但是没有回到颤抖的视图。

所以这是正确的方法。 Flutter Navigation Using Coordinator Pattern

答案 2 :(得分:1)

在 Swift 中,我们可以使用方法通道从 Flutter 动作事件中打开原生 iOS viewController, 在flutter中,需要添加以下几行来触发iOS原生方法。在您的操作方法中添加这些行

var platform = const MethodChannel('navigation');
final String result = await platform.invokeMethod('IOS');

在 iOS 中,在 AppDelegate 应用程序方法中添加以下几行。

let controller : FlutterViewController = window?.rootViewController as! FlutterViewController
let methodChannel = FlutterMethodChannel(name: "navigation", binaryMessenger:controller.binaryMessenger)
navigationController = UINavigationController(rootViewController: controller)
navigationController.setNavigationBarHidden(true, animated: false)
self.window!.rootViewController = navigationController
self.window!.makeKeyAndVisible()
methodChannel.setMethodCallHandler({
    (call: FlutterMethodCall, result: @escaping FlutterResult) -> 
    Void in
if call.method == "IOS" {
      let vc = "Your viewController"(nibName: "Your 
      viewController", bundle: nil)
      navigationController.pushViewController(vc, animated: 
     false)
} else {
         result(FlutterMethodNotImplemented)
         return
}
})

本机视图控制器后退按钮操作。

self.navigationController?.popViewController(animated: true)

谢谢。

答案 3 :(得分:0)

Writing custom platform-specific code

带有按钮的小部件。点击按钮应推送依赖消息,将视图控制器推送到iOS应用。

class BodyWidget extends StatelessWidget {

  static const platform = const MethodChannel('samples.flutter.dev/navigation_channel');

  Future<void> _pushOnNative() async {
    try {
      Map parameters = Map();
      parameters["title"] = "Contact Details";
      parameters["name"] = "Bang Operator";
      parameters["so_profile_exists"] = true;
      await platform.invokeMethod('push',[parameters]);
    } on PlatformException catch (e) {
      print("Failed to communicate level: '${e.message}'.");
    }
  }

  @override
  Widget build(BuildContext context) {
    return Center(
        child: FlatButton(
          textColor: Colors.white,
          color: Colors.red,
          onPressed: _pushOnNative,
          child: Text('Push Me'),
        )
    );
  }
}

在iOS应用方面, 我们需要观察方法'push'的通道samples.flutter.dev/navigation_channel。 我们还可以从颤动端传递参数,在本示例中,我们传递一个以NSDictionary(Obj-C)形式接收的Map(Dart)

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

  FlutterViewController *controller = (FlutterViewController*)self.window.rootViewController;
  UINavigationController *navigationController = [[UINavigationController alloc] initWithRootViewController:controller];

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

  [self setupNavigationChannelCallbacksOnMessenger:controller
                           forNavigationController:navigationController];


  return [super application:application didFinishLaunchingWithOptions:launchOptions];
}

- (void)setupNavigationChannelCallbacksOnMessenger:(id<FlutterBinaryMessenger>)messenger
                           forNavigationController:(UINavigationController *)navigationController {
  FlutterMethodChannel* pushChannel = [FlutterMethodChannel
                                       methodChannelWithName:@"samples.flutter.dev/navigation_channel"
                                       binaryMessenger:messenger];

  [pushChannel setMethodCallHandler:^(FlutterMethodCall* call, FlutterResult result) {
    if ([call.method isEqualToString:@"push"] && [self getDictionaryFromArguments:call.arguments]) {
      NSDictionary *parameters = [self getDictionaryFromArguments:call.arguments];
      [self pushContactScreenWithInfo:parameters onNaivgationController:navigationController];
      result(@(true));
    } else {
      result(FlutterMethodNotImplemented);
    }
  }];
}

- (NSDictionary *)getDictionaryFromArguments:(id)arguments {
  if (![arguments isKindOfClass:[NSArray class]]) {
    return nil;
  }
  NSArray *argumentsArray = (NSArray *)arguments;
  if (argumentsArray.firstObject == nil || ![argumentsArray.firstObject isKindOfClass:[NSDictionary class]]) {
    return nil;
  }
  return (NSDictionary *)argumentsArray.firstObject;
}

- (void)pushContactScreenWithInfo:(NSDictionary *)info
          onNaivgationController:(UINavigationController *)navigationContorller {
  UIStoryboard *storyboard = [UIStoryboard storyboardWithName:@"Main" bundle:nil];
  ContactViewController *controller = [storyboard instantiateViewControllerWithIdentifier:@"ContactViewController"];
  [navigationContorller pushViewController:controller animated:YES];
  [controller view];
  [controller configureWithInfo:info];
}