Flutter踩坑日记:接入现有iOS项目
之前搞的Flutter版工具链已经弄完了,感兴趣的朋友可以围观下,Android版本dio库(v2.0.14)发送网络请求老是报错,去官方提了issue还没回,于是今天搞一下把Flutter模块接入到已有项目中。
首先Flutter官方已经出了wiki,教大家怎么接入。懒得看官方原文的可以看看这个简易版快速集成,先来看看效果。
一、创建Flutter模块
一般用Flutter
或者React Native
的团队大部分原因都是因为需要跨平台,所以在已有项目目录的上一级创建Flutter
模块,譬如你的工作目录在some/path/MyApp
,那么你需要在some/path
下执行,这样Flutter
可以单独交给一个虚拟团队维护,各自独立。
$ cd some/path/
$ flutter create -t module my_flutter
文件结构如下:
some/path/
my_flutter/
lib/main.dart
.ios/
MyApp/
MyApp.xcodeproj
Podfile
MyApp/
AppDelegate.h
AppDelegate.m (or swift)
二、利用Cocoapods添加依赖
没用过Cocoapods
的童鞋可以google
搜一下,之前写过很多Cocoapods
的文章由于博客主机商跑路都没了,说多了都是泪
1.在Podfile文件加入以下代码:
flutter_application_path = '../my_flutter/'
eval(File.read(File.join(flutter_application_path, '.ios', 'Flutter', 'podhelper.rb')), binding)
注意my_flutter
的路径,因为我们是以xcodeproj
文件的上一级创建的,所以需要加../,这个和React Native
引入依赖路径是一样的,都需要注意这个问题。
2.执行pod install
注:如果报错
[!] InvalidPodfilefile: No such file or directory @ rb_sysopen - ./my_flutter/.ios/Flutter/podhelper.rb.
需要在my_flutter
文件夹下执行以下flutter run
,把.ios
和.android
等flutter
配置生成出来。
3.禁用bitcode,设置环境变量
找到你的target
,Build Settings->Build Options->Enable Bitcode
设置为NO
,另外在Preprocessor Macros
添加FLUTTER_BUILD_MODE=Debug
和FLUTTER_BUILD_MODE=Release
,如果还有其他环境需要根据情况选择Debug
或Release
。
4.添加run script
找到你的target
,Build Phases -> + -> New Run Script Phase
,并且在bash
或zsh
配置FLUTTER_ROOT
,否则打包会出错找不到flutter
。涉及多人开发还需要安装路径位置,否则团队小伙伴每个人的路径不一样。
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" build
"$FLUTTER_ROOT/packages/flutter_tools/bin/xcode_backend.sh" embed
注:把这个script放到Target Dependencies phasescript的后面。
5.添加assets资源
官网说需要添加Flutter.framework
资源,但是这个Cocoapods
已经帮忙引入了,所以就不需要了,如果没有被引入进去那就手动引入下。这里只需要添加flutter_assets
就行了,记得选Creat folder references
引入方式。Flutter
1.0.0版本路径是my_flutter->build->flutter_assets
6.修改AppDelegate
Objective-C:
AppDelegate.h
#import <UIKit/UIKit.h>
#import <Flutter/Flutter.h>
@interface AppDelegate : FlutterAppDelegate
@property (nonatomic,strong) FlutterEngine *flutterEngine;
@end
AppDelegate.m
#import <FlutterPluginRegistrant/GeneratedPluginRegistrant.h> // Only if you have Flutter Plugins
#include "AppDelegate.h"
@implementation AppDelegate
// This override can be omitted if you do not have any Flutter Plugins.
- (BOOL)application:(UIApplication *)application
didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
self.flutterEngine = [[FlutterEngine alloc] initWithName:@"io.flutter" project:nil];
[self.flutterEngine runWithEntrypoint:nil];
[GeneratedPluginRegistrant registerWithRegistry:self.flutterEngine];
return [super application:application didFinishLaunchingWithOptions:launchOptions];
}
@end
Swift:
AppDelegate.swift
import UIKit
import Flutter
import FlutterPluginRegistrant // Only if you have Flutter Plugins.
@UIApplicationMain
class AppDelegate: FlutterAppDelegate {
var flutterEngine : FlutterEngine?;
// Only if you have Flutter plugins.
override func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.flutterEngine = FlutterEngine(name: "io.flutter", project: nil);
self.flutterEngine?.run(withEntrypoint: nil);
GeneratedPluginRegistrant.register(with: self.flutterEngine);
return super.application(application, didFinishLaunchingWithOptions: launchOptions);
}
}
到这里,我们的Flutter就算已经引入工程了
三、跳转Flutter页面
Objective-C:
ViewController.m
#import <Flutter/Flutter.h>
#import "AppDelegate.h"
#import "ViewController.h"
@implementation ViewController
- (void)viewDidLoad {
[super viewDidLoad];
UIButton *button = [UIButton buttonWithType:UIButtonTypeCustom];
[button addTarget:self
action:@selector(handleButtonAction)
forControlEvents:UIControlEventTouchUpInside];
[button setTitle:@"Press me" forState:UIControlStateNormal];
[button setBackgroundColor:[UIColor blueColor]];
button.frame = CGRectMake(80.0, 210.0, 160.0, 40.0);
[self.view addSubview:button];
}
- (void)handleButtonAction {
FlutterEngine *flutterEngine = [(AppDelegate *)[[UIApplication sharedApplication] delegate] flutterEngine];
FlutterViewController *flutterViewController = [[FlutterViewController alloc] initWithEngine:flutterEngine nibName:nil bundle:nil];
[self presentViewController:flutterViewController animated:false completion:nil];
}
@end
Swift:
ViewController.swift
import UIKit
import Flutter
class ViewController: UIViewController {
override func viewDidLoad() {
super.viewDidLoad()
let button = UIButton(type:UIButtonType.custom)
button.addTarget(self, action: #selector(handleButtonAction), for: .touchUpInside)
button.setTitle("Press me", for: UIControlState.normal)
button.frame = CGRect(x: 80.0, y: 210.0, width: 160.0, height: 40.0)
button.backgroundColor = UIColor.blue
self.view.addSubview(button)
}
@objc func handleButtonAction() {
let flutterEngine = (UIApplication.shared.delegate as? AppDelegate)?.flutterEngine;
let flutterViewController = FlutterViewController(engine: flutterEngine, nibName: nil, bundle: nil)!;
self.present(flutterViewController, animated: false, completion: nil)
}
}
剩下的就是写Flutter
页面逻辑了以及Flutter
模块需要调用Native API
(后面专门写一篇文章)。
写完Flutter
页面,如果要跳转到指定页面使用Flutter
的路由就可以了
Objective-C:
[flutterViewController setInitialRoute:@"route1"];
Swift:
flutterViewController.setInitialRoute("route1")
四、运行
在my_flutter
手动flutter run
一下,或者直接开启热加载,然后就可以在原有的iOS
项目中用Xcoderun
起来了。
$ flutter attach --isolate-filter='debug'
Waiting for a connection from Flutter...
Done.
Syncing files to device... 1.1s
Flutter踩坑日记:接入现有iOS项目的更多相关文章
- Flutter踩坑日记:解除依赖
Flutter已经融入工程有一段时间了,由于团队人数较少,所以一直没有管和原有工程解依赖的问题,今天有时间正好把这个问题给搞了. 一.分析 首先,直接忽略上一篇<接入现有iOS项目>的所有 ...
- Flutter踩坑日记:Tab导航栏保持子页面状态
最近应邀票圈小伙伴躺坑Flutter,项目初步雏形完结.以原来的工具链版本为基础做了Flutter版本,不过后面还是需要优化下项目接入Redux,以及扩展一些Native方法. 这里记录一下在开发过程 ...
- cocos creator踩坑日记
踩坑一 问题:项目在构建成Web Mobile后运行在浏览器和微信中,点击页面任何地方都会导致自动全屏 解决:在构建之后的main.js中,去掉 cc.view.enableAutoFullScree ...
- Hexo搭建静态博客踩坑日记(二)
前言 Hexo搭建静态博客踩坑日记(一), 我们说到利用Hexo快速搭建静态博客. 这节我们就来说一下主题的问题与主题的基本修改操作. 起步 chrome github hexo git node.j ...
- Hexo搭建静态博客踩坑日记(一)
前言 博客折腾一次就好, 找一个适合自己的博客平台, 专注于内容进行提升. 方式一: 自己买服务器, 域名, 写前端, 后端(前后分离最折腾, 不分离还好一点)... 方式二: 利用Hexo, Hug ...
- 现有iOS项目集成React Native过程记录
在<Mac系统下React Native环境搭建>配置了RN的开发环境,然后,本文记录在现有iOS项目集成React Native的过程,官方推荐使用Cocoapods,项目一开始也是使用 ...
- AI相关 TensorFlow -卷积神经网络 踩坑日记之一
上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...
- 人工智能(AI)库TensorFlow 踩坑日记之一
上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...
- hexo博客谷歌百度收录踩坑日记
title: hexo博客谷歌百度收录踩坑日记 toc: false date: 2018-04-17 00:09:38 百度收录文件验证 无论怎么把渲染关掉或者render_skip都说我的格式错误 ...
随机推荐
- 第81讲:Scala中List的构造和类型约束逆变、协变、下界详解
今天来学习一下scala中List的构造和类型约束等内容. 让我们来看一下代码 package scala.learn /** * @author zhang */abstract class Big ...
- Naive Bayes 笔记
Naive Bayes (朴素贝叶斯) 属于监督学习算法, 它通过计算测试样本在训练样本各个分类中的概率来确定测试样本所属分类, 取最大概率为其所属分类. 优点 在数据较少的情况下仍然有效,可以处 ...
- hdu 4911 求逆序对数+树状数组
http://acm.hdu.edu.cn/showproblem.php?pid=4911 给定一个序列,有k次机会交换相邻两个位置的数,问说最后序列的逆序对数最少为多少. 实际上每交换一次能且只能 ...
- excel设定备选值
excel设定备选值 有的时候我们要人为向excel中某一列添加数据,可以通过下面的方法,为这列设定备选值. 操作方法 选中excel表格的一列,选择 数据 -- 有效性 -- 允许: 选择 序列 ...
- MCU_数码管常用表
共阴极数码管编码(0---F) unsigned char code table[]={ 0x3f,0x06,0x5d,0x4f, 0x66,0x6d,0x77,0x7c, 0x39,0x5e,0x7 ...
- 分形之希尔伯特-皮亚诺(Hilbert-Peano)曲线
1890年,意大利数学家皮亚诺(Peano G)发明能填满一个正方形的曲线,叫做皮亚诺曲线.后来,由希尔伯特作出了这条曲线,又名希尔伯特曲线.Hilbert-Peano曲线是一种分形图形,它可以画得无 ...
- Linux-IO重定向与管道
1. 输入与输出 标准输入 STDIN 文件描述符:0,默认:键盘输入 标准输出 STDOUT 文件描述符:1,默认:屏幕输出 错误输出 STDERR 文件描述符:2,默认:屏幕输出 2. 标准输出重 ...
- java 异步机制与同步机制的区别
所谓异步输入输出机制,是指在进行输入输出处理时,不必等到输入输出处理完毕才返回.所以异步的同义语是非阻塞(None Blocking). 网上有很多网友用很通俗的比喻 把同步和异步讲解的很透彻 转过 ...
- XAML 调试工具 不见了?
XAML调试工具不见了怎么办? 1.调试---> 选项---> 选中 启用XAML的UI调试工具 2.调试---> 选项---> 禁用 使用托管兼容模式 欧了!
- .NET MVC 学习笔记(六)— 数据导入
.NET MVC 学习笔记(六)—— 数据导入 在程序使用过程中,有时候需要新增大量数据,这样一条条数据去Add明显不是很友好,这时候最好就是有一个导入功能,导入所需要的数据,下面我们就一起来看一下导 ...