当前位置:   article > 正文

swift项目嵌入flutter的module混合开发(framework模式:适合多人协作开发,一个负责混合开发)_flutter嵌入已有swift

flutter嵌入已有swift

和之前一样,这个模块也是对于本地我们开发好的代码,需要到一起开发iOS的同事需要拉代码,调试的时候。这种静态包的方式就会好很多。不用在他的电脑上也搭建flutter环境,以及创建flutter项目的拉取调试等复杂的工作再做一遍。

 

综上所述,多人协作开发ios的项目,一人负责混合的flutter的module内容的,可以用到这种framework的形式会比较好。

但是他的弊端就是需要每次运行在项目中的时候需要负责混合开发的人员先运行一下flutter项目生成一些必要的framework。

 

这里我们来进行两种方式来操作我们的framework:

  1.还是本地的项目生成之后将framework直接加入到项目中依赖使用

  2.将framework通过cocoapods进行版本管理导入项目(就是将第一种作为一个git管理便捷多人开发的一种方式而已)

 

首先我们来说第一种:

1.1、  创建iOS项目

在电脑桌面Desktop创建外层文件夹 FlutterAddIOSOptionB,并在该文件下创建iOS工程iOSProject,依次执行以下命令

  1. $ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB/MyApp
  2. $ pod init
  3. $ pod install

1.2. 接下来创建名字为‘ FlutteriOSPod’的Pod库

  1. $ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB
  2. $ pod lib create FlutteriOSPod

终端依次输入所需类型:

  1. $ pod lib create FlutteriOSPod
  2. Cloning `https://github.com/CocoaPods/pod-template.git` into `FlutteriOSPod`.
  3. Configuring FlutteriOSPod template.
  4. ------------------------------
  5. To get you started we need to ask a few questions, this should only take a minute.
  6. What platform do you want to use?? [ iOS / macOS ]
  7.  > iOS
  8. What language do you want to use?? [ Swift / ObjC ]
  9.  > Swift
  10. Would you like to include a demo application with your library? [ Yes / No ]
  11.  > No
  12. Which testing frameworks will you use? [ Specta / Kiwi / None ]
  13.  > None
  14. Would you like to do view based testing? [ Yes / No ]
  15.  > No
  16. Running pod install on your new library.

创建完成之后会有一个工程自动打开,此工程为Pod工程,在Example->FlutteriOSPod.xcworkspace打开后可以作为独立项目在此编码iOS代码之类的,暂时先不在此进行编写原生代码,关闭退出。

当前项目目录构造:

 

 

1.3.  在FlutteriOSPod目录下创建 Flutter  Module模块

  1. $ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB/FlutteriOSPod
  2. $ flutter create -t module flutter_module_for_ios

命令执行完后,目录文件夹下会多出一个名为flutter_module_for_ios的flutter模板项目

该项目模板包含有flutter代码模块+隐藏.ios文件。同时选中三个键可以使隐藏文件显示

command + shift + .

在当前flutter_module_for_ios文件lib中可以编码flutter相关代码,考虑到可能会在flutter项目中使用到相关插件,我们可以在pubspec.yaml中添加一个插件(如果有项目的话就可以使用自己的项目,这里只是模拟一个flutter项目开发,在文中下面我用的是现有的项目)

  1. dependencies:
  2.   flutter:
  3.     sdk: flutter
  4.   cupertino_icons: ^0.1.2
  5.   #添加 数据持久化插件  https://pub.flutter-io.cn/packages/shared_preferences
  6.   shared_preferences: ^0.5.4+3

 

1.4、在flutter_module_for_ios项目中执行安装插件操作

  1. $ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB/FlutteriOSPod/flutter_module_for_ios/
  2. $ flutter pub get

可以看到在.ios文件夹下自动生成出来一个Podfile文件.(这里图中的.lock、Pods文件、.xcworkspace都是下面编译后的产物。这里我就偷懒直接用这个图了。看到这点不同不要惊讶呦)

 

1.5、执行编译该flutter_module_for_ios项目

编译后会生成Flutter所依赖的相关的库文件。我们在当前先编译出debug版本的库文件方便我们后续调试

  1. $ flutter build ios --debug      //编译debug产物
  2. 或者
  3. $ flutter build ios --release --no-codesign //编译release产物(选择不需要证书)

观察项目中的变化,可发现有多出编译产物(这些就是flutter中编译出的静态包,引用库不同这里的包也会不同,不要惊讶。这里主要是看位置)(这里的Debug-iphonesimulator文件是在flutter项目下运行flutter run -d all运行在iphone模拟器下生成的,而Release-iphones文件是上一步编译release的产物)

 

 

我们所需要的就是这些生成出来的framework库

build目录下

ios->Debug-iphoneos->  FlutterPluginRegistrant.framework

ios->Debug-iphoneos-> 。。。(你项目中的使用第三方).framework

.ios目录下

Flutter-->App.framework Flutter-->engine-->Flutter.framework

当前生成的库都是debug版本库文件。 需要注意的是,后续若想编译出release版本的framework库,修改下面的脚本文件根据注释提示修改。因为在build生成产物之前会先重置文件为初始状态

接下来iOS工程通过Pod把这些库引入到自己的工程中了。为了方便集中快速管理操作我们可以通过创建脚本的方式对其进行管理(思路就是通过脚本创建一个文件夹,将这些散乱在各文件的库统一拷贝进来)

2.1、在flutter_module_for_ios下创建脚本文件

  1. $ cd ../flutter_module_for_ios
  2. $ touch move_file_debug.sh   //1. 创建生成debug模式的脚本文件
  3. open move_file_debug.sh    //2. 打开debug模式的脚本文件
  4. //同样下面的内容修改处做下改动,生成另外一个脚本move_file_release.sh来做release版本生成

添加以下脚本代码

  1. if [ -z $out ]; then
  2.     out='ios_frameworks'
  3. fi
  4. echo "准备输出所有文件到目录: $out"
  5. echo "清除所有已编译文件"
  6. find . -d -name build | xargs rm -rf
  7. flutter clean
  8. rm -rf $out
  9. rm -rf build
  10. flutter packages get
  11. addFlag(){
  12.     cat .ios/Podfile > tmp1.txt
  13.     echo "use_frameworks!" >> tmp2.txt
  14.     cat tmp1.txt >> tmp2.txt
  15.     cat tmp2.txt > .ios/Podfile
  16.     rm tmp1.txt tmp2.txt
  17. }
  18. echo "检查 .ios/Podfile文件状态"
  19. a=$(cat .ios/Podfile)
  20. if [[ $a == use* ]]; then
  21.     echo '已经添加use_frameworks, 不再添加'
  22. else
  23.     echo '未添加use_frameworks,准备添加'
  24.     addFlag
  25.     echo "添加use_frameworks 完成"
  26. fi
  27. echo "编译flutter"
  28. flutter build ios --debug
  29. #release下放开下一行注释,注释掉上一行代码
  30. #flutter build ios --release --no-codesign
  31. echo "编译flutter完成"
  32. mkdir $out
  33. cp -r build/ios/Debug-iphoneos/*/*.framework $out
  34. #release下放开下一行注释,注释掉上一行代码
  35. #cp -r build/ios/Release-iphoneos/*/*.framework $out
  36. cp -r .ios/Flutter/App.framework $out
  37. cp -r .ios/Flutter/engine/Flutter.framework $out
  38. echo "复制framework库到临时文件夹: $out"
  39. libpath='../'
  40. rm -rf "$libpath/ios_frameworks"
  41. mkdir $libpath
  42. cp -r $out $libpath
  43. echo "复制库文件到: $libpath"

注意观察脚本文件中的代码意思:将编译生成的debug版本的所需.framework库文件拷贝至ios_frameworks文件下并复制一份到FlutteriOSPod目录下,后续若想编译生成release版本库文件时还需修改脚本文件查找对应上release标识


2.2、执行脚本文件
 

$ sh move_file_debug(release).sh      //3. 执行脚本文件

此时的ios_frameworks文件已经生成拷贝

里面包含有我们前面提到所需要的.framework所有库文件

 

接下来我们就要通过FlutteriOSPod库的podspec来创建依赖导出

3.1、编辑podspec文件

打开podspec文件在end前一行添加以下命令

  1.   s.static_framework = true
  2.   p = Dir::open("ios_frameworks")
  3.   arr = Array.new
  4.   arr.push('ios_frameworks/*.framework')
  5.   s.ios.vendored_frameworks = arr

添加之后文件整体长这样

 

 

3.2、在iOSProject项目的podfile文件中执行pod引用

在iOSProject工程下的podfile文件中添加

  1. # Uncomment the next line to define a global platform for your project
  2. platform :ios, '10.0'
  3. source 'https://github.com/CocoaPods/Specs.git'
  4. target 'MyApp' do
  5. # Comment the next line if you don't want to use dynamic frameworks
  6. use_frameworks!
  7. pod 'Alamofire'
  8. pod 'SnapKit'
  9. #flutter
  10. pod 'FlutteriOSPod', :path => '../FlutteriOSPod'
  11. end

之后执行

$ pod install

终端提示安装FlutteriOSPod库成功

其中FlutteriOSPod库里就包含有我们所需的上述提到的framework库

 

OK下面我们来试一下如何在iOS项目中跳转进flutter界面,也就是我们提到的混合开发的代码测试,基本上也就是按照官方提供的模板写

4.1、AppDelegate.swift中修改

  1. //
  2. // AppDelegate.swift
  3. // MyApp
  4. //
  5. // Created by 曹世鑫 on 2020/3/4.
  6. // Copyright © 2020 曹世鑫. All rights reserved.
  7. //
  8. import UIKit
  9. import FlutterPluginRegistrant
  10. import Flutter
  11. @UIApplicationMain
  12. class AppDelegate: UIResponder, UIApplicationDelegate {
  13. lazy var flutterEngine = FlutterEngine(name: "com.brainco.gameEngine")
  14. var window: UIWindow?
  15. func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
  16. self.window?.rootViewController = UINavigationController.init(rootViewController: ViewController())
  17. self.window?.backgroundColor = .white
  18. self.window?.makeKeyAndVisible()
  19. initEngine()
  20. return true
  21. }
  22. private func initEngine() {
  23. flutterEngine.run();
  24. GeneratedPluginRegistrant.register(with: flutterEngine);
  25. }
  26. }

4.2、ViewController.swift

  1. //
  2. // ViewController.swift
  3. // MyApp
  4. //
  5. // Created by 曹世鑫 on 2020/3/4.
  6. // Copyright © 2020 曹世鑫. All rights reserved.
  7. //
  8. import UIKit
  9. import Flutter
  10. class ViewController: UIViewController {
  11. override func viewDidLoad() {
  12. super.viewDidLoad()
  13. // Do any additional setup after loading the view.
  14. self.title = "原生页面"
  15. let btn: UIButton = UIButton()
  16. btn.backgroundColor = .cyan
  17. btn.frame = CGRect(x: 50, y: 100, width: 100, height: 50)
  18. btn.addTarget(self, action: #selector(btnChoose), for: .touchUpInside)
  19. self.view.addSubview(btn);
  20. }
  21. @objc func btnChoose() {
  22. let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
  23. let flutterViewController = FlutterViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
  24. // self.navigationController?.pushViewController(flutterViewController, animated: true)
  25. present(flutterViewController, animated: true, completion: {
  26. print("结果如下")
  27. })
  28. }
  29. }

 

集成代码较官方方式有部分不同,这里没有通过 lazy var flutterEngine = FlutterEngine(name: "com.brainco.gameEngine") 这种方式去初始化引擎,是因为FlutterViewContorller在new的时候会自动的创建一个引擎。而通过官方的方式去初始化引擎则需将该引擎设置成一个全局单例去使用

至此。第一种形式的pod本地化引入工程就已经完成。但是我们发现一个问题那就是目前感觉好像还是没有能完全剥离一台电脑上没有flutter环境配置的情况下如何去引入flutter.framework等库文件,难道要手动拷贝么,这样也不是很符合开发的初衷,接下来我会给大家介绍一下如何将创建好的私有库上传至git去托管,然后其他开发同学直接通过Git命令去引入包,这样也就从根源上解决了模块化的剥离,更为干净利落


这里项目中由于我们的代码管理是在github上面,这里我就以github来添加一个处理。至于其他的平台代码管理的话可以参考我之前写的一系列组件库的搭建,已经很详细(这里就不再赘述了)快捷传送门点这里

下面我们就开始github提交库索引。(其实github只是省了一步索引库的创建,弊端就是,git的网络不太稳定,使用git的索引库有点烦网络问题。

声明:本文内容由网友自发贡献,不代表【wpsshop博客】立场,版权归原作者所有,本站不承担相应法律责任。如您发现有侵权的内容,请联系我们。转载请注明出处:https://www.wpsshop.cn/w/我家小花儿/article/detail/383228
推荐阅读
相关标签