Flutter混合开发IOS篇
在Mac上搭建Flutter开发环境
1.下载Flutter SDK ((Channel stable, v1.17.1, on Mac OS X 10.15.7 19H15, locale zh-Hans-CN),不要下载最新的SDK,兼容混合开发框架 flutter_boost: ^1.17.1。
2.下载四个插件,分别为 Flutter、Dart、FishReduxTemplate、Flutter Intl。流程图如下:
Preferences | Plugins
3.检查三个SDK的配置,分别为Androd SDK、Flutter SDK、
Dart SDK. 流程图如下:
Preferences | Appearance & Behavior | System Settings | Android SDK
Preferences | Languages & Frameworks | Flutter
Preferences | Languages & Frameworks | Dart
IOS Flutter混合开发
创建module
1.在IOS项目的同级目录新建Flutter Module
File | New | New Flutter Project… | Flutter Module
2.Flutter module项目集成FlutterBoost
在flutter_module项目的pubspec.yaml文件中添加依赖插件配置
dependencies:
flutter_boost: ^1.17.1
配置完成后执行flutter packages get命令下载依赖插件到本地
需要了解 pub get 和 pub upgrade 命令 , 打开pubspec.yaml这两个命令就能显示出来
pub get
在项目中配置了pubspec文件后,就可以在项目根目录中执行pub get命令
pub upgrade
第一次获取依赖时,Pub 会下载依赖及其兼容的最新版本。然后通过创建lockfile 锁定依赖,以始终使用这个版本。 Pub会在pubspec旁创建并存储一个名为pubspec.lock文件。它列出了使用的每个依赖包的指定版本(当前包或传递包的版本)。
3.运行代码
1.直接点击绿色的箭头Run就能独立运行到手机里面。
2.Build | Flutter | Build AAR ,就能编译出AAR文件,并生成Android集成日志
IOS原生项目中集成FlutterBoost
1. 修改 Podfile 文件
flutter_application_path = '../flutter_module/'
load File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')
target 'YiHome2.0' do
install_all_flutter_pods(flutter_application_path)
2.运行命令
pod install
3.添加 PlatformRouterImp.h
//
// PlatformRouterImp.h
// YiHome2.0
//
// Created by liubing on 2020/11/26.
// Copyright © 2020 xiaoyi. All rights reserved.
//
#import <Foundation/Foundation.h>
#import <UIKit/UIKit.h>
#import <flutter_boost/FlutterBoost.h>
NS_ASSUME_NONNULL_BEGIN
@protocol FLBPlatform;
/**
* 实现平台侧的页面打开和关闭,不建议直接使用用于页面打开,建议使用FlutterBoostPlugin中的open和close方法来打开或关闭页面;
* FlutterBoostPlugin带有页面返回数据的能力
*/
@interface PlatformRouterImp : NSObject<FLBPlatform>
@property (nonatomic,strong) UINavigationController *navigationController;
@end
NS_ASSUME_NONNULL_END
4.添加 PlatformRouterImp.m
//
// PlatformRouterImp.m
// YiHome2.0
//
// Created by liubing on 2020/11/26.
// Copyright © 2020 xiaoyi. All rights reserved.
//
#import "PlatformRouterImp.h"
#import <flutter_boost/FlutterBoost.h>
#import "JJDeviceShareQRCodeScanSuccessViewController.h"
@interface PlatformRouterImp()
- (UINavigationController *)currentNC;
@end
@implementation PlatformRouterImp
#pragma mark - Boost 1.5
- (void)open:(NSString *)name
urlParams:(NSDictionary *)params
exts:(NSDictionary *)exts
completion:(void (^)(BOOL))completion
{
if ([name isEqualToString:@"yicamera://DeviceShareResultActivity"]) {
// KeyConst.DEVICE_SHARE_WAY: KeyConst.DEVICE_SHARE_WAY_ACCOUNT,
// KeyConst.DEVICE_SHARE_MESSAGE_ID: infoInvitee.id,
// KeyConst.DEVICE_SHARE_TOKEN: infoInvitee.shareToken,
// KeyConst.DEVICE_SHARE_OWNER_NAME: infoInvitee.nickName,
JJDeviceShareQRCodeScanSuccessViewController * vc = DYY_Create_Alloc(JJDeviceShareQRCodeScanSuccessViewController);
vc.stringInvitedUserId = params[@"DEVICE_SHARE_OWNER_NAME"];
vc.stringShareToken = params[@"DEVICE_SHARE_TOKEN"];
int type = 2;
vc.shareType = type == 2 ? JJShareTypeAccount : JJShareTypeQRCode;
[[self currentNC] pushViewController:vc animated:YES];
// TODO 设备邀请
return;
}
BOOL animated = [exts[@"animated"] boolValue];
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[[self currentNC] pushViewController:vc animated:animated];
if(completion) completion(YES);
}
- (void)present:(NSString *)name
urlParams:(NSDictionary *)params
exts:(NSDictionary *)exts
completion:(void (^)(BOOL))completion
{
BOOL animated = [exts[@"animated"] boolValue];
FLBFlutterViewContainer *vc = FLBFlutterViewContainer.new;
[vc setName:name params:params];
[[self currentNC] presentViewController:vc animated:animated completion:^{
if(completion) completion(YES);
}];
}
- (void)close:(NSString *)uid
result:(NSDictionary *)result
exts:(NSDictionary *)exts
completion:(void (^)(BOOL))completion
{
BOOL animated = [exts[@"animated"] boolValue];
animated = YES;
FLBFlutterViewContainer *vc = (id)[self currentNC].presentedViewController;
if([vc isKindOfClass:FLBFlutterViewContainer.class] && [vc.uniqueIDString isEqual: uid]){
[vc dismissViewControllerAnimated:animated completion:^{}];
}else{
[[self currentNC] popViewControllerAnimated:animated];
}
}
- (UINavigationController *)currentNC
{
if (![[UIApplication sharedApplication].windows.lastObject isKindOfClass:[UIWindow class]]) {
NSAssert(0, @"未获取到导航控制器");
return nil;
}
UIViewController *rootViewController = [UIApplication sharedApplication].keyWindow.rootViewController;
return [self getCurrentNCFrom:rootViewController];
}
//递归
- (UINavigationController *)getCurrentNCFrom:(UIViewController *)vc
{
if ([vc isKindOfClass:[UITabBarController class]]) {
UINavigationController *nc = ((UITabBarController *)vc).selectedViewController;
return [self getCurrentNCFrom:nc];
}
else if ([vc isKindOfClass:[UINavigationController class]]) {
if (((UINavigationController *)vc).presentedViewController) {
return [self getCurrentNCFrom:((UINavigationController *)vc).presentedViewController];
}
return [self getCurrentNCFrom:((UINavigationController *)vc).topViewController];
}
else if ([vc isKindOfClass:[UIViewController class]]) {
if (vc.presentedViewController) {
return [self getCurrentNCFrom:vc.presentedViewController];
}
else {
return vc.navigationController;
}
}
else {
NSAssert(0, @"未获取到导航控制器");
return nil;
}
}
@end
5.修改 AppDelegate.h
#import <flutter_boost/FlutterBoost.h>
6.修改 AppDelegate.m
#import "AppDelegate.h"
#import "PlatformRouterImp.h"
#import <flutter_boost/FlutterBoost.h>
...
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
...
router = [PlatformRouterImp new];
[FlutterBoostPlugin.sharedInstance startFlutterWithPlatform:router
onStart:^(FlutterEngine *engine) {
// 注册MethodChannel,监听flutter侧的getPlatformVersion调用
FlutterMethodChannel *flutterMethodChannel = [FlutterMethodChannel methodChannelWithName:@"flutter_native_channel" binaryMessenger:engine.binaryMessenger];
[flutterMethodChannel setMethodCallHandler:^(FlutterMethodCall * _Nonnull call, FlutterResult _Nonnull result) {
NSString *method = call.method;
if ([@"getUser" isEqualToString:call.method]) {
dispatch_async(dispatch_get_global_queue(0, 0), ^{
NSError *error = nil;
[JJSingleAccount sharedJJSingleAccount];
JJSingleAccount *account = [JJSingleAccount sharedJJSingleAccount];
NSString *user = [account mj_JSONString];
NSDictionary *r = @{@"user":user};
NSData *data = [NSJSONSerialization dataWithJSONObject:r options:NSJSONWritingPrettyPrinted error:&error];
result(data);
});
} else if ([method isEqualToString:@"getPlatformVersion"]) {
NSString *sysVersion = [[UIDevice currentDevice] systemVersion];
result(sysVersion);
} else {
result(FlutterMethodNotImplemented);
}
}];
}];
return YES;
}
7. 打开Flutter界面
[FlutterBoostPlugin open:@"notification" urlParams:nil exts:@{@"animated":@(YES)}onPageFinished:^(NSDictionary *result) {
NSLog(@"call me when page finished, and your result is:%@", result);
} completion:^(BOOL f) {
NSLog(@"page is opened");
}];
学习资料
Flutter官网
Dart官网
依赖包
OpenFlutter社区
flutter_boost 混合开发框架
fish_redux架构开发