之前搞的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.androidflutter配置生成出来。

3.禁用bitcode,设置环境变量

找到你的targetBuild Settings->Build Options->Enable Bitcode设置为NO,另外在Preprocessor Macros添加FLUTTER_BUILD_MODE=DebugFLUTTER_BUILD_MODE=Release,如果还有其他环境需要根据情况选择DebugRelease

4.添加run script

找到你的targetBuild Phases -> + -> New Run Script Phase,并且在bashzsh配置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项目的更多相关文章

  1. Flutter踩坑日记:解除依赖

    Flutter已经融入工程有一段时间了,由于团队人数较少,所以一直没有管和原有工程解依赖的问题,今天有时间正好把这个问题给搞了. 一.分析 首先,直接忽略上一篇<接入现有iOS项目>的所有 ...

  2. Flutter踩坑日记:Tab导航栏保持子页面状态

    最近应邀票圈小伙伴躺坑Flutter,项目初步雏形完结.以原来的工具链版本为基础做了Flutter版本,不过后面还是需要优化下项目接入Redux,以及扩展一些Native方法. 这里记录一下在开发过程 ...

  3. cocos creator踩坑日记

    踩坑一 问题:项目在构建成Web Mobile后运行在浏览器和微信中,点击页面任何地方都会导致自动全屏 解决:在构建之后的main.js中,去掉 cc.view.enableAutoFullScree ...

  4. Hexo搭建静态博客踩坑日记(二)

    前言 Hexo搭建静态博客踩坑日记(一), 我们说到利用Hexo快速搭建静态博客. 这节我们就来说一下主题的问题与主题的基本修改操作. 起步 chrome github hexo git node.j ...

  5. Hexo搭建静态博客踩坑日记(一)

    前言 博客折腾一次就好, 找一个适合自己的博客平台, 专注于内容进行提升. 方式一: 自己买服务器, 域名, 写前端, 后端(前后分离最折腾, 不分离还好一点)... 方式二: 利用Hexo, Hug ...

  6. 现有iOS项目集成React Native过程记录

    在<Mac系统下React Native环境搭建>配置了RN的开发环境,然后,本文记录在现有iOS项目集成React Native的过程,官方推荐使用Cocoapods,项目一开始也是使用 ...

  7. AI相关 TensorFlow -卷积神经网络 踩坑日记之一

    上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...

  8. 人工智能(AI)库TensorFlow 踩坑日记之一

    上次写完粗浅的BP算法 介绍 本来应该继续把 卷积神经网络算法写一下的 但是最近一直在踩 TensorFlow的坑.所以就先跳过算法介绍直接来应用场景,原谅我吧. TensorFlow 介绍 TF是g ...

  9. hexo博客谷歌百度收录踩坑日记

    title: hexo博客谷歌百度收录踩坑日记 toc: false date: 2018-04-17 00:09:38 百度收录文件验证 无论怎么把渲染关掉或者render_skip都说我的格式错误 ...

随机推荐

  1. hdu 4969 平面几何积分

    http://acm.hdu.edu.cn/showproblem.php?pid=4969 Guizeyanhua要去追一个女孩,女孩在以Guizeyanhua为圆心,半径为R的圆上匀速运动,女孩的 ...

  2. [kuangbin]树链剖分 D - 染色

    https://vjudge.net/contest/251031#problem/Dhttps://blog.csdn.net/kirito_acmer/article/details/512019 ...

  3. 2018/6/29 关于hashmap的总结

    hashMap和ConcurrentHashMap的区别 hashMap内部具体如何实现的 如果hashMap的key是一个自定义的类,怎么办 为什么重写equals还要重写hashcode 一.什么 ...

  4. Mac下替代Total Commander的工具推荐

    [推荐]:Nimble Commander 轻量小巧,免费版与收费版区别不大,比较稳定,支持sftp等其他网络存储,支持自定义热键,预览等. http://magnumbytes.com/ [其他]: ...

  5. QT中的一些信号

    QLineEdit: 通过改变QLineEdit的echoMode(),可以设置其属性,比如以密码的形式输入. 文本的长度可以由maxLength()限制,可以通过使用validator()或者inp ...

  6. python 通过pytz模块进行时区的转换,获取指定时区的时间

    import pytz import time import datetime print(pytz.country_timezones('cn')) # 查询中国所拥有的时区 print(pytz. ...

  7. css3的帧动画

    概述 前几天刚好看到一个用了CSS3帧动画的页面,对它非常感兴趣,就研究了一下,记录在下面,供以后开发时参考,相信对其他人也有用. PS:以后别人问我用过什么CSS3属性的时候,我也可以不用说常见的a ...

  8. 修改tomcat默认端口号

    修改tomcat端口号 端口修改tomcat tomcat服务器的默认端口号是8080 1 只启动一个tomcat的情况 当我们不想使用8080端口,需要修改为其他端口时,我们可以: 1, 打开tom ...

  9. spring-boot集成thymeleaf。

    thymeleaf是前台页面展示,原来一直是jsp,jsp中包含很多服务器端的逻辑,逐渐淘汰.同样功能的还有freemarker.孰好孰坏不予评价,只做简单实现. 1.基本思路 (1)pom.xml中 ...

  10. Linux - 针对用户账号的常用操作

    用户目录 除root用户外,其他默认的用户目录一般为/home/<user name>. 可以通过如下步骤修改默认用户目录 修改/etc/passwd文件中相应用户的路径信息 停止此用户的 ...