Flutter教程:iOS原生和Flutter交互

flutter主動和iOS交互

flutter MyApp界面裡1、flutter點擊事件之後 iOS跳轉界面2、flutter傳map類型參數給iOS進行相應交互3、在flutter界面的事件響應之後,iOS返回響應數據給flutter

iOS代碼如下:
<code>
#import "ViewController.h"
#import "TargetViewController.h"
#import <flutter>

@interface ViewController ()

@end

@implementation ViewController

- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view, typically from a nib.
}


- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)pushFlutterViewController {
FlutterViewController* flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
// 設置路由名字 跳轉到不同的flutter界面
/*flutter代碼*/
/*
import 'dart:ui';

void main() => runApp(_widgetForRoute(window.defaultRouteName));

Widget _widgetForRoute(String route) {
switch (route) {
case 'myApp':
return new MyApp();
case 'home':
return new HomePage();
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}
*/
[flutterViewController setInitialRoute:@"myApp"];

__weak __typeof(self) weakSelf = self;

// 要與main.dart中一致
NSString *channelName = @"com.pages.your/native_get";

FlutterMethodChannel *messageChannel = [FlutterMethodChannel methodChannelWithName:channelName binaryMessenger:flutterViewController];

[messageChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
// call.method 獲取 flutter 給回到的方法名,要匹配到 channelName 對應的多個 發送方法名,一般需要判斷區分
// call.arguments 獲取到 flutter 給到的參數,(比如跳轉到另一個頁面所需要參數)
// result 是給flutter的回調, 該回調只能使用一次
NSLog(@"method=%@ \\narguments = %@", call.method, call.arguments);

// method和WKWebView裡面JS交互很像
// flutter點擊事件執行後在iOS跳轉TargetViewController
if ([call.method isEqualToString:@"iOSFlutter"]) {
TargetViewController *vc = [[TargetViewController alloc] init];
[self.navigationController pushViewController:vc animated:YES];
}
// flutter傳參給iOS
if ([call.method isEqualToString:@"iOSFlutter1"]) {
NSDictionary *dic = call.arguments;
NSLog(@"arguments = %@", dic);
NSString *code = dic[@"code"];
NSArray *data = dic[@"data"];
NSLog(@"code = %@", code);
NSLog(@"data = %@",data);
NSLog(@"data 第一個元素%@",data[0]);
NSLog(@"data 第一個元素類型%@",[data[0] class]);
}
// iOS給iOS返回值
if ([call.method isEqualToString:@"iOSFlutter2"]) {
if (result) {
result(@"返回給flutter的內容");
}
}
}];

[self.navigationController pushViewController:flutterViewController animated:YES];
}
// 點擊跳轉到flutter界面
- (void)touchesBegan:(NSSet<uitouch> *)touches withEvent:(UIEvent *)event {
[self pushFlutterViewController];
}

@end

/<uitouch>/<flutter>/<code>
flutter代碼
<code>import 'dart:ui' as ui; // 調用window拿到route判斷跳轉哪個界面
import 'package:flutter/material.dart';
import 'package:flutter/services.dart';
import 'package:flutter_module/HomePage.dart';


void main() => runApp(_widgetForRoute(ui.window.defaultRouteName));

// 根據iOS端傳來的route跳轉不同界面
Widget _widgetForRoute(String route) {
switch (route) {
case 'myApp':
return new MyApp();
case 'home':
return new HomePage();
default:
return Center(
child: Text('Unknown route: $route', textDirection: TextDirection.ltr),
);
}
}

class MyApp extends StatelessWidget {

Widget _home(BuildContext context) {
return new MyHomePage(title: 'Flutter Demo Home Page');
}

@override
Widget build(BuildContext context) {
return new MaterialApp(
title: 'Flutter Demo',
theme: new ThemeData(
primarySwatch: Colors.blue,

),
routes: <string>{
"/home":(BuildContext context) => new HomePage(),
},
home: _home(context),
);
}
}

class MyHomePage extends StatefulWidget {
MyHomePage({Key key, this.title}) : super(key: key);

final String title;

@override
_MyHomePageState createState() => new _MyHomePageState();
}

class _MyHomePageState extends State<myhomepage> {

// 創建一個給native的channel (類似iOS的通知)
static const methodChannel = const MethodChannel('com.pages.your/native_get');


_iOSPushToVC() async {
await methodChannel.invokeMethod('iOSFlutter', '參數');
}

_iOSPushToVC1() async {
Map<string> map = {"code": "200", "data":[1,2,3]};
await methodChannel.invokeMethod('iOSFlutter1', map);
}

_iOSPushToVC2() async {
dynamic result;
try {
result = await methodChannel.invokeMethod('iOSFlutter2');
} on PlatformException {
result = "error";
}
if (result is String) {
print(result);
showModalBottomSheet(context: context, builder: (BuildContext context) {
return new Container(
child: new Center(
child: new Text(result, style: new TextStyle(color: Colors.brown), textAlign: TextAlign.center,),
),
height: 40.0,
);

});
}
}

@override
Widget build(BuildContext context) {
return new Scaffold(
body: new Center(
child: new Column(
mainAxisAlignment: MainAxisAlignment.center,
children: <widget>[
new FlatButton(onPressed: () {
_iOSPushToVC();
}, child: new Text("跳轉ios新界面,參數是字符串")),
new FlatButton(onPressed: () {
_iOSPushToVC1();
}, child: new Text("傳參,參數是map,看log")),
new FlatButton(onPressed: () {
_iOSPushToVC2();
}, child: new Text("接收客戶端相關內容")),
],
),
),
);
}
}


/<widget>/<string>/<myhomepage>/<string>/<code>

iOS主動和flutter交互

flutter MyApp界面裡1、初始化flutter界面時候iOS傳值給flutter

iOS代碼
<code>
#import "TargetViewController.h"
#import <flutter>

@interface TargetViewController () <flutterstreamhandler>

@end

@implementation TargetViewController


- (void)viewDidLoad {
[super viewDidLoad];
self.title = @"TargetViewController";
self.view.backgroundColor = [UIColor whiteColor];
}

- (void)didReceiveMemoryWarning {
[super didReceiveMemoryWarning];
// Dispose of any resources that can be recreated.
}

- (void)pushFlutterViewController_EventChannel {
FlutterViewController* flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
flutterViewController.navigationItem.title = @"Demo";
[flutterViewController setInitialRoute:@"home"];
// 要與main.dart中一致
NSString *channelName = @"com.pages.your/native_post";

FlutterEventChannel *evenChannal = [FlutterEventChannel eventChannelWithName:channelName binaryMessenger:flutterViewController];
// 代理FlutterStreamHandler
[evenChannal setStreamHandler:self];

[self.navigationController pushViewController:flutterViewController animated:YES];
}

#pragma mark - <flutterstreamhandler>
// // 這個onListen是Flutter端開始監聽這個channel時的回調,第二個參數 EventSink是用來傳數據的載體。
- (FlutterError* _Nullable)onListenWithArguments:(id _Nullable)arguments
eventSink:(FlutterEventSink)events {
// arguments flutter給native的參數
// 回調給flutter, 建議使用實例指向,因為該block可以使用多次
if (events) {
events(@"push傳值給flutter的vc");
}
return nil;
}

/// flutter不再接收
- (FlutterError* _Nullable)onCancelWithArguments:(id _Nullable)arguments {
// arguments flutter給native的參數
NSLog(@"%@", arguments);
return nil;

}

- (void)touchesBegan:(NSSet<uitouch> *)touches withEvent:(UIEvent *)event {
[self pushFlutterViewController_EventChannel];
}

@end

/<uitouch>/<flutterstreamhandler>/<flutterstreamhandler>/<flutter>/<code>
flutter代碼
<code>import 'package:flutter/material.dart';
import 'package:flutter/services.dart';

class HomePage extends StatefulWidget {
_HomePageState createState() => _HomePageState();
}

class _HomePageState extends State<homepage> {

// 註冊一個通知
static const EventChannel eventChannel = const EventChannel('com.pages.your/native_post');

// 渲染前的操作,類似viewDidLoad
@override
void initState() {
super.initState();

// 監聽事件,同時發送參數12345
eventChannel.receiveBroadcastStream(12345).listen(_onEvent,onError: _onError);
}

String naviTitle = 'title' ;
// 回調事件
void _onEvent(Object event) {
setState(() {
naviTitle = event.toString();
});
}
// 錯誤返回
void _onError(Object error) {

}

@override
Widget build(BuildContext context) {

return new MaterialApp(
home: new Material(
child: new Scaffold(
body: new Center(
child: new Text(naviTitle),
),
),
),
);
}
}

/<homepage>/<code>


分享到:


相關文章: