swift項目嵌入flutter的module混合開發(framework模式:適合多人協作開發,一個負責混合開發)

和之前一樣,這個模塊也是對於本地我們開發好的代碼,需要到一起開發iOS的同事需要拉代碼,調試的時候。這種靜態包的方式就會好很多。不用在他的電腦上也搭建flutter環境,以及創建flutter項目的拉取調試等複雜的工作再做一遍。

 

綜上所述,多人協作開發ios的項目,一人負責混合的flutter的module內容的,可以用到這種framework的形式會比較好。

但是他的弊端就是需要每次運行在項目中的時候需要負責混合開發的人員先運行一下flutter項目生成一些必要的framework。

 

這裏我們來進行兩種方式來操作我們的framework:

  1.還是本地的項目生成之後將framework直接加入到項目中依賴使用

  2.將framework通過cocoapods進行版本管理導入項目(就是將第一種作爲一個git管理便捷多人開發的一種方式而已)

 

首先我們來說第一種:

1.1、  創建iOS項目

在電腦桌面Desktop創建外層文件夾 FlutterAddIOSOptionB,並在該文件下創建iOS工程iOSProject,依次執行以下命令

$ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB/MyApp
$ pod init
$ pod install

1.2. 接下來創建名字爲‘ FlutteriOSPod’的Pod庫

$ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB
$ pod lib create FlutteriOSPod

終端依次輸入所需類型:

$ pod lib create FlutteriOSPod
Cloning `https://github.com/CocoaPods/pod-template.git` into `FlutteriOSPod`.
Configuring FlutteriOSPod template.
------------------------------
To get you started we need to ask a few questions, this should only take a minute.

What platform do you want to use?? [ iOS / macOS ]
 > iOS
What language do you want to use?? [ Swift / ObjC ]
 > Swift
Would you like to include a demo application with your library? [ Yes / No ]
 > No
Which testing frameworks will you use? [ Specta / Kiwi / None ]
 > None
Would you like to do view based testing? [ Yes / No ]
 > No

Running pod install on your new library.

創建完成之後會有一個工程自動打開,此工程爲Pod工程,在Example->FlutteriOSPod.xcworkspace打開後可以作爲獨立項目在此編碼iOS代碼之類的,暫時先不在此進行編寫原生代碼,關閉退出。

當前項目目錄構造:

 

 

1.3.  在FlutteriOSPod目錄下創建 Flutter  Module模塊

$ cd /Users/caoshixin/Desktop/FlutterAddIOSOptionB/FlutteriOSPod
$ 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項目開發,在文中下面我用的是現有的項目)

dependencies:
  flutter:
    sdk: flutter
  cupertino_icons: ^0.1.2
  #添加 數據持久化插件  https://pub.flutter-io.cn/packages/shared_preferences
  shared_preferences: ^0.5.4+3

 

1.4、在flutter_module_for_ios項目中執行安裝插件操作

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

可以看到在.ios文件夾下自動生成出來一個Podfile文件.(這裏圖中的.lock、Pods文件、.xcworkspace都是下面編譯後的產物。這裏我就偷懶直接用這個圖了。看到這點不同不要驚訝呦)

 

1.5、執行編譯該flutter_module_for_ios項目

編譯後會生成Flutter所依賴的相關的庫文件。我們在當前先編譯出debug版本的庫文件方便我們後續調試

$ flutter build ios --debug      //編譯debug產物
或者
$ 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下創建腳本文件

$ cd ../flutter_module_for_ios
$ touch move_file_debug.sh   //1. 創建生成debug模式的腳本文件
$ open move_file_debug.sh    //2. 打開debug模式的腳本文件
//同樣下面的內容修改處做下改動,生成另外一個腳本move_file_release.sh來做release版本生成

添加以下腳本代碼

if [ -z $out ]; then
    out='ios_frameworks'
fi

echo "準備輸出所有文件到目錄: $out"

echo "清除所有已編譯文件"
find . -d -name build | xargs rm -rf
flutter clean
rm -rf $out
rm -rf build

flutter packages get

addFlag(){
    cat .ios/Podfile > tmp1.txt
    echo "use_frameworks!" >> tmp2.txt
    cat tmp1.txt >> tmp2.txt
    cat tmp2.txt > .ios/Podfile
    rm tmp1.txt tmp2.txt
}

echo "檢查 .ios/Podfile文件狀態"
a=$(cat .ios/Podfile)
if [[ $a == use* ]]; then
    echo '已經添加use_frameworks, 不再添加'
else
    echo '未添加use_frameworks,準備添加'
    addFlag
    echo "添加use_frameworks 完成"
fi

echo "編譯flutter"
flutter build ios --debug
#release下放開下一行註釋,註釋掉上一行代碼
#flutter build ios --release --no-codesign
echo "編譯flutter完成"
mkdir $out
cp -r build/ios/Debug-iphoneos/*/*.framework $out
#release下放開下一行註釋,註釋掉上一行代碼
#cp -r build/ios/Release-iphoneos/*/*.framework $out
cp -r .ios/Flutter/App.framework $out
cp -r .ios/Flutter/engine/Flutter.framework $out

echo "複製framework庫到臨時文件夾: $out"

libpath='../'

rm -rf "$libpath/ios_frameworks"
mkdir $libpath
cp -r $out $libpath

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前一行添加以下命令

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

添加之後文件整體長這樣

 

 

3.2、在iOSProject項目的podfile文件中執行pod引用

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

# Uncomment the next line to define a global platform for your project
platform :ios, '10.0'
source 'https://github.com/CocoaPods/Specs.git'

target 'MyApp' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  pod 'Alamofire'
  pod 'SnapKit'

 #flutter
  pod 'FlutteriOSPod', :path => '../FlutteriOSPod'

end

之後執行

$ pod install

終端提示安裝FlutteriOSPod庫成功

其中FlutteriOSPod庫裏就包含有我們所需的上述提到的framework庫

 

OK下面我們來試一下如何在iOS項目中跳轉進flutter界面,也就是我們提到的混合開發的代碼測試,基本上也就是按照官方提供的模板寫

4.1、AppDelegate.swift中修改

//
//  AppDelegate.swift
//  MyApp
//
//  Created by 曹世鑫 on 2020/3/4.
//  Copyright © 2020 曹世鑫. All rights reserved.
//

import UIKit
import FlutterPluginRegistrant
import Flutter

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
    
    lazy var flutterEngine = FlutterEngine(name: "com.brainco.gameEngine")
    var window: UIWindow?
    
    
    func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
        
        self.window?.rootViewController = UINavigationController.init(rootViewController: ViewController())
        self.window?.backgroundColor = .white
        self.window?.makeKeyAndVisible()
        initEngine()
        
        return true
    }
    
    private func initEngine() {

        flutterEngine.run();
        GeneratedPluginRegistrant.register(with: flutterEngine);
    }
    
    
}

4.2、ViewController.swift

//
//  ViewController.swift
//  MyApp
//
//  Created by 曹世鑫 on 2020/3/4.
//  Copyright © 2020 曹世鑫. All rights reserved.
//

import UIKit
import Flutter

class ViewController: UIViewController {
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view.
        self.title = "原生頁面"
               
        let btn: UIButton = UIButton()
        btn.backgroundColor = .cyan
        btn.frame = CGRect(x: 50, y: 100, width: 100, height: 50)
        btn.addTarget(self, action: #selector(btnChoose), for: .touchUpInside)
        self.view.addSubview(btn);
        
    }
    
    @objc func btnChoose() {
        let flutterEngine = (UIApplication.shared.delegate as! AppDelegate).flutterEngine
        let flutterViewController = FlutterViewController.init(engine: flutterEngine, nibName: nil, bundle: nil)
        
//        self.navigationController?.pushViewController(flutterViewController, animated: true)
        present(flutterViewController, animated: true, completion: {
            print("結果如下")
        })
    }

}

 

集成代碼較官方方式有部分不同,這裏沒有通過 lazy var flutterEngine = FlutterEngine(name: "com.brainco.gameEngine") 這種方式去初始化引擎,是因爲FlutterViewContorller在new的時候會自動的創建一個引擎。而通過官方的方式去初始化引擎則需將該引擎設置成一個全局單例去使用

至此。第一種形式的pod本地化引入工程就已經完成。但是我們發現一個問題那就是目前感覺好像還是沒有能完全剝離一臺電腦上沒有flutter環境配置的情況下如何去引入flutter.framework等庫文件,難道要手動拷貝麼,這樣也不是很符合開發的初衷,接下來我會給大家介紹一下如何將創建好的私有庫上傳至git去託管,然後其他開發同學直接通過Git命令去引入包,這樣也就從根源上解決了模塊化的剝離,更爲乾淨利落


這裏項目中由於我們的代碼管理是在github上面,這裏我就以github來添加一個處理。至於其他的平臺代碼管理的話可以參考我之前寫的一系列組件庫的搭建,已經很詳細(這裏就不再贅述了)快捷傳送門點這裏

下面我們就開始github提交庫索引。(其實github只是省了一步索引庫的創建,弊端就是,git的網絡不太穩定,使用git的索引庫有點煩網絡問題。😂)

1.1、遠程創建倉庫FlutteriOSPod

 

1.2、在FlutteriOSPod項目中與遠端建立連接(這裏我鏈接遠端之後後面提交不上,使用的是將遠端庫glone到本地這個文件,將之前的這個pod文件裏面的文件全部移過來了)(可以不使用下面的這個git代碼,這裏主要是要爲了將後面我們的代碼以及tag能夠做到提交遠端處理)

$ cd ../FlutteriOSPod
$ git remote add origin https:。。。(你的倉庫地址).git

爲了防止上傳文件過大的限制,可以選擇在.gitignore文件中選擇不上傳flutter_module_for_ios代碼,只將ios_frameworks文件中的庫文件上傳就好

1.2.1、gitignore文件

image.png

$ git add .
$ git commit -m "Initial data commit"
$ git push -u origin master

將我們的代碼以及tag添加提交到託管平臺。

 

1.3、修改FlutteriOSPod.podspec文件(下面的圖片僅供參考,主要是一些信息必須是自己的)

image.png

需要注意的地方時你自己創建的gitlab地址與管理員郵箱及tag版本一一對應上

將此修改的文件推至遠端倉庫並打上tag推送至遠端

$ git status
$ git add MyFlutterPod.podspec
$ git commit -m "修改文件"
$ git push origin master

// 給當前代碼設置tag版本
$ git tag -a 0.0.1 -m 'Initial tag commit'
$ git push --tags

 

1.4、驗證一下Pod庫文件是否可行

$ pod spec lint MyFlutterPod.podspec --verbose

驗證通過之後

1.4.1、接下來就是將我們的FlutteriOSPod.podspec索引文件推送至github索引庫(這裏我的是私有庫就不需要了,直接進行1.5的驗證就可以了)

1>發佈時會驗證 Pod 的有效性,如果你在手動驗證 Pod 時使用了 --use-libraries 或 --allow-warnings 等修飾符,那麼發佈的時候也應該使用相同的字段修飾,否則出現相同的報錯。


// --use-libraries --allow-warnings
pod trunk push FlutteriOSPod.podspec

如果是公有庫還需要發佈到cocoaPods trunk上。私有庫就不用了。如果私有庫發佈到trunk上會報錯。

[!] Source code for your Pod was not accessible to CocoaPods Trunk. Is it a private repo or behind a username/password on http?


2>等待......................................
3>最後進行驗證 

在trunk push後,先用"pod search"查找一下你的代碼,有結果的話就歡天喜地;

沒有的話執行"pod setup"進行本地依賴庫更新,再search。

這裏github的上傳參考我的另一篇文章文章:創建GitHub私有庫,製作CocoaPods依賴庫

1.5、在MyApp文件中進行添加代碼

如果在此之前做過本地化加載pod庫,要先卸載掉之前安裝過的文件 --1 註釋掉podfile文件中的代碼 pod 'FlutteriOSPod', :path => '../FlutteriOSPod' --2執行一下 pod install 可以看到之前安裝過得庫已經從項目中移除

修改podfile文件

# Uncomment the next line to define a global platform for your project
platform :ios, '8.0'

target 'iOSProject' do
  # Comment the next line if you don't want to use dynamic frameworks
  use_frameworks!

  # Pods for iOSProject
#   pod 'FlutteriOSPod', :path => '../FlutteriOSPod'
   pod 'FlutteriOSPod',:git=>'https:...(對應的git地址).git',:tag=>'0.0.1'

end

安裝過程可能會比較慢,這跟網絡有關
 

(擴展延伸)

pod指定路徑下載第三方庫

pod 版本庫名, :git => 版本庫地址

pod 'xxx' , :git => 'https://github.com/xxx/xxx_ios.git'

如果下載下來發現缺少了文件,應該是未指定版本號,使用pod+路徑+版本號下載

pod 'xxx' , :git => 'https://github.com/xxx/xxx_ios.git' , :tag => '3.4.4'

 

1.6、下載完畢的項目目錄下可以看到添加進的framework庫文件

 


2.1、可以試一下按照方式一中的代碼切換進flutter頁面,這裏就不貼代碼了

至此,通過Git遠程管理的flutter模塊集成進iOS項目已經完成了,以後每次flutter模塊代碼有更新時,直接推向遠端,iOS開發同學直接在podfile文件中進行拉取,後續可以考慮加上tag標識來進行拉取

優點: 對 Flutter 自身的構建流程改動較少並且較徹底第解決了本地耦合的問題; 解決了組件式開發的痛點,各自開發各自的代碼,也不用要求每臺電腦上都配置flutter環境

缺點: 集成方式上變得貌似更加繁瑣,Flutter 內容的變動需要先同步到遠程倉庫再 同步到 Standalone 模式方能生效;且要各自打包維護iOS安卓的兩套代碼倉庫供不同平臺去拉取調用

 

 

 

發表評論
所有評論
還沒有人評論,想成為第一個評論的人麼? 請在上方評論欄輸入並且點擊發布.
相關文章