前言

Flutter 是一个很有潜力的框架,但是目前使用Flutter的APP并不算很多,相关资料并不丰富,介绍现有工程引入Flutter的相关文章也比较少。项目从零开始,引入Flutter操作比较简单,但是现有工程引入Flutter 需要费很多精力和时间,这里是我在完成现有iOS工程引入Flutter后写的一次总结文章。

Flutter 环境搭建

首先是要搭建Flutter环境,之前也写了一篇相关文章搭建Flutter-iOS开发环境,可以参考一下 可以去官网查看:github.com/flutter/flu… 比较简单,这里不做赘述。

现有iOS工程引入Flutter

一、建立Flutter module

首先建立flutter module,主要是用于获取改flutter app中的Generated.xcconfig和framework

cd some/path/
$ flutter create -t module my_flutter
复制代码

也可以用

flutter create app
复制代码

建立flutter app,flutter app中也有Generated.xcconfig和framework

二、新建配置文件

根据官网,需要在工程中建立三个配置文件: Flutter.xcconfigDebug.xcconfigRelease.xcconfig 在XCode工程对应目录,右击,选择新建文件(New File),选中创建xcconfig文件,如图:

Flutter.xcconfig中填写:
 //这里填写前面建立的flutter module 的Generated.xcconfig的路径
#include "../../my_flutter/.ios/Flutter/Generated.xcconfig"
ENABLE_BITCODE=NO
复制代码
Debug.xcconfig中填写:
#include "../Flutter/Flutter.xcconfig"

复制代码

Release.xcconfig中填写:

#include "../Flutter/Flutter.xcconfig"
FLUTTER_BUILD_MODE=release
复制代码

如果工程中用cocoapods管理,需要在 Debug.xcconfigRelease.xcconfig添加pod的路径:

例如 Release.xcconfig

#include "Flutter.xcconfig"
#include "工程路径/Pods/Target Support Files/******.release.xcconfig"//pod路径
FLUTTER_BUILD_MODE=release
复制代码

在准备好这些xcconfig文件后,需要到XCode工程PROJECT(注意是PROJECT,不是Target)中的Configuration选项里,将对应的target选择成前面的xcconfig文件,Debug用Debug.xcconfig, Release用 Release.xcconfig

注意:进行Archive打包的时候,无论是Debug包还是Release包,需要切换到Release.xcconfig,不然会报错。

三、为编译Dart引入相关build phase

在工程的Build Phase中新建一个Run Script,用于编译时运行脚本, 建立方法如图:

建立Run Script后,需要移动其对应的位置,需要在Target dependencies之后,如果用cocoapods管理工程需要在,Check Pods Manifest.lock之后:

在脚本框中,填入以下代码,用于引进Flutter中的xcode_backend脚本:

"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
复制代码

如图:

四、生成和添加Framework

完成前面的配置后,便可以在XCode对工程进行编译build (Command+B),在提示“ Build Success ” 后,在iOS工程文件夹中会生成一个Flutter文件夹,将其加入工程目录中,建议和刚才xcconfig所在目录并列,

右键项目目录 ,选择 Add Files to 'xxx' ,Options选Create groups,添加编译生成的Flutter文件夹。需要注意但是:Flutter目录下有个flutter_assets文件,不能使用Create groups的方式添加,只能用Creat folder references的Options, 否则Flutter页面会空白渲染不出来。可以删了flutter_assets在用Creat folder references重新添加。

在添加完Flutter 文件夹之后,去Embeded Binaries中添加App.frameworkFlutter.framework

五、AppDelegate改造

Flutter需要和APP进行交互,需要对AppDelegate 进行改造:

AppDelegate.h文件中:

#import <Flutter/Flutter.h>

@interface AppDelegate : FlutterAppDelegate <UIApplicationDelegate, FlutterAppLifeCycleProvider>

@end
复制代码

AppDelegate.m 文件中:

#import "AppDelegate.h"

@interface AppDelegate ()

@end

@implementation AppDelegate
{
FlutterPluginAppLifeCycleDelegate *_lifeCycleDelegate;
} - (instancetype)init {
if (self = [super init]) {
_lifeCycleDelegate = [[FlutterPluginAppLifeCycleDelegate alloc] init];
}
return self;
} - (BOOL)application:(UIApplication*)application
didFinishLaunchingWithOptions:(NSDictionary*)launchOptions {
return [_lifeCycleDelegate application:application didFinishLaunchingWithOptions:launchOptions];
} - (void)applicationDidEnterBackground:(UIApplication*)application {
[_lifeCycleDelegate applicationDidEnterBackground:application];
} - (void)applicationWillEnterForeground:(UIApplication*)application {
[_lifeCycleDelegate applicationWillEnterForeground:application];
} - (void)applicationWillResignActive:(UIApplication*)application {
[_lifeCycleDelegate applicationWillResignActive:application];
} - (void)applicationDidBecomeActive:(UIApplication*)application {
[_lifeCycleDelegate applicationDidBecomeActive:application];
} - (void)applicationWillTerminate:(UIApplication*)application {
[_lifeCycleDelegate applicationWillTerminate:application];
} - (void)application:(UIApplication*)application
didRegisterUserNotificationSettings:(UIUserNotificationSettings*)notificationSettings {
[_lifeCycleDelegate application:application
didRegisterUserNotificationSettings:notificationSettings];
} - (void)application:(UIApplication*)application
didRegisterForRemoteNotificationsWithDeviceToken:(NSData*)deviceToken {
[_lifeCycleDelegate application:application
didRegisterForRemoteNotificationsWithDeviceToken:deviceToken];
} - (void)application:(UIApplication*)application
didReceiveRemoteNotification:(NSDictionary*)userInfo
fetchCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
[_lifeCycleDelegate application:application
didReceiveRemoteNotification:userInfo
fetchCompletionHandler:completionHandler];
} - (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
options:(NSDictionary<UIApplicationOpenURLOptionsKey, id>*)options {
return [_lifeCycleDelegate application:application openURL:url options:options];
} - (BOOL)application:(UIApplication*)application handleOpenURL:(NSURL*)url {
return [_lifeCycleDelegate application:application handleOpenURL:url];
} - (BOOL)application:(UIApplication*)application
openURL:(NSURL*)url
sourceApplication:(NSString*)sourceApplication
annotation:(id)annotation {
return [_lifeCycleDelegate application:application
openURL:url
sourceApplication:sourceApplication
annotation:annotation];
} - (void)application:(UIApplication*)application
performActionForShortcutItem:(UIApplicationShortcutItem*)shortcutItem
completionHandler:(void (^)(BOOL succeeded))completionHandler NS_AVAILABLE_IOS(9_0) {
[_lifeCycleDelegate application:application
performActionForShortcutItem:shortcutItem
completionHandler:completionHandler];
} - (void)application:(UIApplication*)application
handleEventsForBackgroundURLSession:(nonnull NSString*)identifier
completionHandler:(nonnull void (^)(void))completionHandler {
[_lifeCycleDelegate application:application
handleEventsForBackgroundURLSession:identifier
completionHandler:completionHandler];
} - (void)application:(UIApplication*)application
performFetchWithCompletionHandler:(void (^)(UIBackgroundFetchResult result))completionHandler {
[_lifeCycleDelegate application:application performFetchWithCompletionHandler:completionHandler];
} - (void)addApplicationLifeCycleDelegate:(NSObject<FlutterPlugin>*)delegate {
[_lifeCycleDelegate addDelegate:delegate];
} 复制代码

六、新建FlutterViewController

主要配置基本上已经完成,只要在main.dart实现Flutter的业务代码即可

在原有工程中 ,建立FlutterViewController来承载main.dart实现的Flutter页面,如:

    self.flutterViewController = [[FlutterViewController alloc] initWithProject:nil nibName:nil bundle:nil];
[self.navigationController pushViewController:self.flutterViewController animated:YES];
复制代码

后语

到这里现有iOS工程引入Flutter的工作就完成了,一些细节上的修改需要根据场景进行修改,例如Flutter和Native的数据通信等。

Flutter-现有iOS工程引入Flutter的更多相关文章

  1. Flutter 集成到现有iOS工程

    前沿 由于我司已经有自己的App,flutter属于技术引进的一部分,也不太可能重新启动一个项目,因此目前我们是将flutter模块形式注入我们的App之中.即:将flutter模块集成到现在有iOS ...

  2. Cordova-在现有iOS工程自动化接入Cordova插件

    模拟Cordova插件命令 自己编写脚本,了解cordova添加插件做了哪些事情. 上一篇文章了解到,web与native的交互主要是cordova.js中的exec方法调用,触发交互事件.UIWeb ...

  3. iOS工程引入ios-charts-master

    前一段时间看到一个非常好的例子ios-charts-master,想在自己的工程中引用,但是一直没有成功,即使把整个工程原封不动的搬过来仍然,无济于事. 经过一次意外研究,终于成功了. 特记下集成过程 ...

  4. 【Flutter 混合开发】添加 Flutter 到 iOS

    Flutter 混合开发系列 包含如下: 嵌入原生View-Android 嵌入原生View-iOS 与原生通信-MethodChannel 与原生通信-BasicMessageChannel 与原生 ...

  5. Flutter踩坑日记:接入现有iOS项目

    之前搞的Flutter版工具链已经弄完了,感兴趣的朋友可以围观下,Android版本dio库(v2.0.14)发送网络请求老是报错,去官方提了issue还没回,于是今天搞一下把Flutter模块接入到 ...

  6. iOS 工程实现native 跳转指定的Flutter 页面

    概要 在前一篇文章中我们提到,iOS跳转到Flutter工程指定页面时(多个),Flutter只有单例,设置setInitialRouter 无效,如下 let flutterViewControll ...

  7. 升级添加到现有iOS Xcode项目的Flutter

    如果你在2019年8月之前将Flutter添加到现有iOS项目,本文值得你一看. 在2019年7月30日,合并合并请求flutter / flutter#36793之前Flutter 1.8.4-pr ...

  8. iOS开发者学习Flutter

    Flutter for iOS 开发者 本文档适用那些希望将现有 iOS 经验应用于 Flutter 的开发者.如果你拥有 iOS 开发基础,那么你可以使用这篇文档开始学习 Flutter 的开发. ...

  9. 现有项目中集成Flutter

    本文列举了项目开发使用Flutter会遇到的问题,以及如何使用Flutter module在现有项目中集成Flutter,并对其原理进行了分析. 最近在做的一个商业项目,完全的使用Flutter编写的 ...

随机推荐

  1. 自定义基于IFC数据的施工进度数据结构

    <DataSource>D:/qlbz20190802.ifc</DataSource> <Datas> <Data> <ID></I ...

  2. java调用科大讯飞流式(websocket)语音识别接口

    要使用讯飞的能力,需先注册讯飞开发平台账号(讯飞官网参见https://www.xfyun.cn/). 再创建应用,点击右上角的控制台 -> 创建新应用: 每个应用都有一个appId,由这个ap ...

  3. Qt编写自定义控件45-柱状标尺控件

    一.前言 这个控件写了很久了,是最早期的一批控件中的一个,和温度计控件类似,都是垂直的进度条,可以设置不同的背景颜色,左侧的刻度也可以自由设定,还提供了动画效果,其实就是开启定时器慢慢的进度到设定的目 ...

  4. LeetCode_110. Balanced Binary Tree

    110. Balanced Binary Tree Easy Given a binary tree, determine if it is height-balanced. For this pro ...

  5. 【Leetcode_easy】748. Shortest Completing Word

    problem 748. Shortest Completing Word 题意: solution1: class Solution { public: string shortestComplet ...

  6. Linux清除痕迹

    Linux清除痕迹 第一种方法: 在退出会话前直接执行: #history -r 清除当前会话的命令历史记录 第二种方法: 在vim中执行自己不想让别人看到的命令 随便用vim打开一个文件 :set ...

  7. 数据结构与算法学习(二)——Master公式及其应用

    本篇文章涉及公式,由于博客园没有很好的支持,建议移步我的CSDN博客和简书进行阅读. 1. Master公式是什么? 我们在解决算法问题时,经常会用到递归.递归在较难理解的同时,其算法的复杂度也不是很 ...

  8. redis 设置后台守护运行的两种方式

    第一种:进入src目录,执行 nohup ./redis-server & 第二种:redis.conf==> daemonize=yes,启动redis-server后面加redis. ...

  9. NLog文章系列—系列文章目录以及简要介绍

    参考文章:http://www.cnblogs.com/dflying/archive/2006/12/04/581750.aspx

  10. 判断scrollView的滑动方向(二)

    在上一篇文章<判断scrollView的滑动方向>中谈到的第二种方法是根据滑动速率来判断的. 今天将通过滑动过程中的坐标差来判断 - (void)scrollViewDidScroll:( ...