我想"推"在我们的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。
答案 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,
var platform = const MethodChannel('com.nativeActivity/iosChannel');
final String result = await platform.invokeMethod('StartNativeIOS');
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];
}