Flutter1系→Flutter2系へupgradeとNull Safety移行で気をつけたいCocoaPodsとRubyのversion

21 min read読了の目安(約19000字

はじめに

既存のFlutterプロジェクトをFlutter1系からFlutter2系にアップグレードしNull Safety移行しました。一筋縄ではいきませんでしたのでハマった部分と対応方法を書こうと思います。

CocoaPodsのversionとRubyのversionには気をつけてください。

対象の読者

  • Flutter1系からFlutter2系に移行しようとしている方。
  • iOSでアプリを実行する方。

詳しく書いていない事

  • Null Safetyに対応したソースコードについて。

前提

  • すでにFlutterのversion1系をインストール済みの状態。
  • カウンターアプリが実行済みの環境。
  • rbenv導入済みの状態
  • Xcode Version 12.4
  • 移行前のFlutterのversionは1.22.5 Dartのversionは2.10.4です。
$ flutter --version
Flutter 1.22.5 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 7891006299 (5 months ago)2020-12-10 11:54:40 -0800
Engine • revision ae90085a84
Tools • Dart 2.10.4

Flutter2に上げる

stableであるか確認する

https://flutter.dev/docs/development/tools/sdk/upgrading#switching-flutter-channels
$ flutter channel
Flutter channels:
  master
  dev
  beta
* stable

upgrade

https://flutter.dev/docs/development/tools/sdk/upgrading#upgrading-the-flutter-sdk
$ flutter upgrade
Flutter 2.0.6 • channel stable • https://github.com/flutter/flutter.git
Framework • revision 1d9032c7e1 (23 hours ago)2021-04-29 17:37:58 -0700
Engine • revision 05e680e202
Tools • Dart 2.12.3

Running flutter doctor...
Doctor summary (to see all details, run flutter doctor -v):
[] Flutter (Channel stable, 2.0.6, on Mac OS X 10.15.6 19G73 darwin-x64, locale ja-JP)
[] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[!] Xcode - develop for iOS and macOS
    ! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
        CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
        Without CocoaPods, plugins will not work on iOS or macOS.
        For more info, see https://flutter.dev/platform-plugins
      To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.
[] Chrome - develop for the web
[] Android Studio (version 4.0)
[!] IntelliJ IDEA Ultimate Edition (version 2016.2.4)
    ✗ This install is older than the minimum recommended version of 2017.1.0.
[] VS Code (version 1.30.0)
[] Connected device (2 available)

無事upgradeできたと思いきや以下の部分の解消が必要です。

[!] Xcode - develop for iOS and macOS
! CocoaPods 1.9.3 out of date (1.10.0 is recommended).
CocoaPods is used to retrieve the iOS and macOS platform side's plugin code that responds to your plugin usage on the Dart side.
Without CocoaPods, plugins will not work on iOS or macOS.
For more info, see https://flutter.dev/platform-plugins
To upgrade see https://guides.cocoapods.org/using/getting-started.html#installation for instructions.

CocoaPodsのversionを1.10.0に上げる

現在のversionを確認

$ pod --version
1.9.3

update

https://guides.cocoapods.org/using/getting-started.html#updating-cocoapods
$ gem install cocoapods
Fetching: activesupport-5.2.5.gem (100%)
Successfully installed activesupport-5.2.5
Fetching: public_suffix-4.0.6.gem (100%)
Successfully installed public_suffix-4.0.6
Fetching: addressable-2.7.0.gem (100%)
Successfully installed addressable-2.7.0
Fetching: cocoapods-core-1.10.1.gem (100%)
Successfully installed cocoapods-core-1.10.1
Fetching: xcodeproj-1.19.0.gem (100%)
Successfully installed xcodeproj-1.19.0
Fetching: cocoapods-1.10.1.gem (100%)
Successfully installed cocoapods-1.10.1
Parsing documentation for activesupport-5.2.5
Installing ri documentation for activesupport-5.2.5
Parsing documentation for public_suffix-4.0.6
Installing ri documentation for public_suffix-4.0.6
Parsing documentation for addressable-2.7.0
Installing ri documentation for addressable-2.7.0
Parsing documentation for cocoapods-core-1.10.1
Installing ri documentation for cocoapods-core-1.10.1
Parsing documentation for xcodeproj-1.19.0
Installing ri documentation for xcodeproj-1.19.0
Parsing documentation for cocoapods-1.10.1
Installing ri documentation for cocoapods-1.10.1
Done installing documentation for activesupport, public_suffix, addressable, cocoapods-core, xcodeproj, cocoapods after 11 seconds
6 gems installed

version確認

$ pod --version
1.10.1

flutter doctor

$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[] Flutter (Channel stable, 2.0.6, on Mac OS X 10.15.6 19G73 darwin-x64, locale ja-JP)
[] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[] Xcode - develop for iOS and macOS
[] Chrome - develop for the web
[] Android Studio (version 4.0)
[!] IntelliJ IDEA Ultimate Edition (version 2016.2.4)
    ✗ This install is older than the minimum recommended version of 2017.1.0.
[] VS Code (version 1.30.0)
[] Connected device (2 available)

! Doctor found issues in 1 category.

Null Safety移行

基本的にはドキュメントに従って進めれば問題ないはずです。

Flutterプロジェクトに移動

$ cd /your_flutter_project

導入packageがNull Safetyに対応済みか確認

$ dart pub outdated --mode=null-safety
  ╔════════════════════════════════════════════════════════════════════════════╗
  ║ The Dart tool uses Google Analytics to anonymously report feature usage    ║
  ║ statistics and to send basic crash reports. This data is used to help      ║
  ║ improve the Dart platform and tools over time.                             ║
  ║                                                                            ║
  ║ To disable reporting of anonymous analytics, run:                          ║
  ║                                                                            ║
  ║   dart --disable-analytics                                                 ║
  ║                                                                            ║
  ╚════════════════════════════════════════════════════════════════════════════╝

Showing dependencies that are currently not opted in to null-safety.
[] indicates versions without null safety support.
[] indicates versions opting in to null safety.

Package Name            Current    Upgradable  Resolvable           Latest               

direct dependencies:   
cloud_firestore         ✗0.16.0+1  ✗0.16.0+1   ✓1.0.7               ✓1.0.7               
cupertino_icons         ✗0.1.3     ✗0.1.3      ✓1.0.2               ✓1.0.2               
firebase_analytics      ✗7.0.1     ✗7.0.1      ✓8.0.2               ✓8.0.2               
firebase_crashlytics    ✗0.4.0+1   ✗0.4.0+1    ✓2.0.2               ✓2.0.2               
firebase_performance    ✗0.5.0+1   ✗0.5.0+1    ✓0.7.0+2             ✓0.7.0+2             
geoflutterfire          ✗2.2.2     ✗2.2.2      ✓3.0.0-nullsafety.2  ✓3.0.0-nullsafety.2  
geolocator              ✗6.2.1     ✗6.2.1      ✓7.0.3               ✓7.0.3               
google_maps_flutter     ✗1.2.0     ✓2.0.3      ✓2.0.3               ✓2.0.3               
share                   ✗0.6.5+4   ✓2.0.1      ✓2.0.1               ✓2.0.1               
shared_preferences      ✗0.5.12+4  ✓2.0.5      ✓2.0.5               ✓2.0.5               
url_launcher            ✗5.7.10    ✓6.0.3      ✓6.0.3               ✓6.0.3               

dev_dependencies:      
flutter_launcher_icons  ✗0.8.1     ✓0.9.0      ✓0.9.0               ✓0.9.0               
flutter_native_splash   ✗0.3.2     ✓1.1.8+4    ✓1.1.8+4             ✓1.1.8+4             
pedantic_mono           ✗1.10.0+4  ✓1.11.0+2   ✓1.11.0+2            ✓1.12.0-dev          

7 upgradable dependencies are locked (in pubspec.lock) to older versions.
To update these dependencies, use `dart pub upgrade`.

7  dependencies are constrained to versions that are older than a resolvable version.
To update these dependencies, edit pubspec.yaml, or run `dart pub upgrade --null-safety`.

package upgrade

https://dart.dev/null-safety/migration-guide#update-dependencies
$ dart pub upgrade --null-safety
Resolving dependencies... (3.3s)

***
***
***

Changed 14 constraints in pubspec.yaml:
  cloud_firestore: any -> ^1.0.7
  firebase_analytics: any -> ^8.0.2
  firebase_crashlytics: any -> ^2.0.2
  firebase_performance: any -> ^0.7.0+2
  geolocator: any -> ^7.0.3
  google_maps_flutter: any -> ^2.0.3
  shared_preferences: any -> ^2.0.5
  url_launcher: any -> ^6.0.3
  geoflutterfire: any -> ^3.0.0-nullsafety.2
  share: any -> ^2.0.1
  cupertino_icons: ^0.1.3 -> ^1.0.2
  pedantic_mono: any -> ^1.11.0+2
  flutter_launcher_icons: any -> ^0.9.0
  flutter_native_splash: any -> ^1.1.8+4

Null Safety対応

マイグレーションツールを使った対応方法

$ dart migrate
See https://dart.dev/go/null-safety-migration for a migration guide.

Analyzing project...
[-----------------------------------------------------------------------------------------------------------------------------------\]No analysis issues found.

Generating migration suggestions...
[------------------------------------------------------------------------------------------------------------------------------------]

Compiling instrumentation information...
[------------------------------------------------------------------------------------------------------------------------------------]

View the migration suggestions by visiting:

 http://127.0.0.1:57359/Users/mizukamitakamasa/Documents/flutter_project/flutter_project_name?authToken=xxxxxxxxxxxx

実行が完了すると以下のURLが生成されます。

http://127.0.0.1:57359/Users/mizukamitakamasa/Documents/flutter_project/flutter_project_name?authToken=xxxxxxxxxxxx

URLを開いてAPPLY MIGRATIONをクリック
View the migration suggestions

手動で気になる部分を修正

iOSアプリ実行

Flutter1系からFlutter2系にアップグレードしNull Safety移行も終わったのでiOSアプリ実行してみます。

$ flutter run
Running pod install...
CocoaPods' output:
↳
      Preparing

    Analyzing dependencies

    Inspecting targets to integrate
      Using `ARCHS` setting to build architectures of target `Pods-Runner`: (``)

    Fetching external sources
    -> Fetching podspec for `Flutter` from `Flutter`
    -> Fetching podspec for `cloud_firestore` from `.symlinks/plugins/cloud_firestore/ios`
    cloud_firestore: Using Firebase SDK version '7.11.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_analytics` from `.symlinks/plugins/firebase_analytics/ios`
    firebase_analytics: Using Firebase SDK version '7.11.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_core` from `.symlinks/plugins/firebase_core/ios`
    firebase_core: Using Firebase SDK version '7.11.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_crashlytics` from `.symlinks/plugins/firebase_crashlytics/ios`
    firebase_crashlytics: Using Firebase SDK version '7.11.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_performance` from `.symlinks/plugins/firebase_performance/ios`
    firebase_performance: Using Firebase SDK version '7.11.0' defined in 'firebase_core'
    -> Fetching podspec for `geolocator` from `.symlinks/plugins/geolocator/ios`
    -> Fetching podspec for `google_maps_flutter` from `.symlinks/plugins/google_maps_flutter/ios`
    -> Fetching podspec for `share` from `.symlinks/plugins/share/ios`
    -> Fetching podspec for `shared_preferences` from `.symlinks/plugins/shared_preferences/ios`
    -> Fetching podspec for `url_launcher` from `.symlinks/plugins/url_launcher/ios`

    Resolving dependencies of `Podfile`
      CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only perfomed in repo update
      CDN: trunk Relative path: all_pods_versions_0_3_5.txt exists! Returning local because checking is only perfomed in repo update
      CDN: trunk Relative path: Specs/0/3/5/Firebase/7.5.0/Firebase.podspec.json exists! Returning local because checking is only perfomed in repo update
      CDN: trunk Relative path: all_pods_versions_a_d_d.txt exists! Returning local because checking is only perfomed in repo update
      CDN: trunk Relative path: Specs/a/d/d/GoogleMaps/4.1.0/GoogleMaps.podspec.json exists! Returning local because checking is only perfomed in repo update
    [!] CocoaPods could not find compatible versions for pod "Firebase/Performance":
      In Podfile:
        firebase_performance (from `.symlinks/plugins/firebase_performance/ios`) was resolved to 0.7.0-2, which depends on
          Firebase/Performance (= 7.11.0)

    None of your spec sources contain a spec satisfying the dependency: `Firebase/Performance (= 7.11.0)`.

    You have either:
     * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
     * mistyped the name or version.
     * not added the source repo that hosts the Podspec to your Podfile.

    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:328:in `raise_error_unless_state'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:310:in `block in unwind_for_conflict'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:308:in `tap'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:308:in `unwind_for_conflict'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:257:in `process_topmost_state'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolution.rb:182:in `resolve'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/molinillo-0.6.6/lib/molinillo/resolver.rb:43:in `resolve'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/resolver.rb:94:in `resolve'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer/analyzer.rb:1074:in `block in resolve_dependencies'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/user_interface.rb:64:in `section'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer/analyzer.rb:1072:in `resolve_dependencies'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer/analyzer.rb:124:in `analyze'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer.rb:414:in `analyze'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer.rb:239:in `block in resolve_dependencies'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/user_interface.rb:64:in `section'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer.rb:238:in `resolve_dependencies'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/installer.rb:160:in `install!'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/command/install.rb:52:in `run'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/claide-1.0.3/lib/claide/command.rb:334:in `run'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/lib/cocoapods/command.rb:52:in `run'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/lib/ruby/gems/2.5.0/gems/cocoapods-1.10.1/bin/pod:55:in `<top (required)>'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/bin/pod:23:in `load'
    /Users/mizukamitakamasa/.rbenv/versions/2.5.0/bin/pod:23:in `<main>'

Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.
To update the CocoaPods specs, run:
  pod repo update

Error running pod install
Error launching application on iPhone 12 Pro Max.

Error: CocoaPods's specs repository is too out-of-date to satisfy dependencies.
To update the CocoaPods specs, run:
pod repo update

pod repo update してくださいとあるのでupdateします。

$ pod repo update
Updating spec repo `master`
***
  Updating files: 100% (20321/20321), done.
  HEAD is now at 0db06a29f0f3 [Add] GoogleMobileAdsMediationFyber 7.8.1.0
Updating spec repo `trunk`

再度iOSアプリ実行

$ flutter run
Running pod install...
    [!] An error occurred while processing the post-install hook of the Podfile.

    undefined method `each_child' for #<Dir:0x00007f8c37b862d8>
    Did you mean?  each_slice

rubyのversionを2.6以上に上げてCocoaPodsを再インストールします。

https://stackoverflow.com/questions/65197799/flutter-pod-install-problem-undefined-method-each-child-for-dir0x00007fa6
$ rbenv install -l
2.5.8
2.6.6
2.7.1
jruby-9.2.13.0
maglev-1.0.0
mruby-2.1.2
rbx-5.0
truffleruby-20.2.0
truffleruby+graalvm-20.2.0
$ ruby --version
ruby 2.5.0p0 (2017-12-25 revision 61468) [x86_64-darwin19]
$ rbenv install 2.7.1
Downloading openssl-1.1.1g.tar.gz...
-> https://dqw8nmjcqpjn7.cloudfront.net/ddb04774f1e32f0c49751e21b67216ac87852ceb056b75209af2443400636d46
Installing openssl-1.1.1g...
Installed openssl-1.1.1g to /Users/mizukamitakamasa/.rbenv/versions/2.7.1

Downloading ruby-2.7.1.tar.bz2...
-> https://cache.ruby-lang.org/pub/ruby/2.7/ruby-2.7.1.tar.bz2
Installing ruby-2.7.1...
ruby-build: using readline from homebrew
Installed ruby-2.7.1 to /Users/mizukamitakamasa/.rbenv/versions/2.7.1
$ rbenv global 2.7.1
$ ruby --version
ruby 2.7.1p83 (2020-03-31 revision a0c7c23c9c) [x86_64-darwin19]
$ gem install cocoapods
$ pod --version
1.10.1
$ flutter doctor
Doctor summary (to see all details, run flutter doctor -v):
[] Flutter (Channel stable, 2.0.6, on Mac OS X 10.15.6 19G73 darwin-x64, locale ja-JP)
[] Android toolchain - develop for Android devices (Android SDK version 30.0.1)
[] Xcode - develop for iOS and macOS
[] Chrome - develop for the web
[] Android Studio (version 4.0)
[!] IntelliJ IDEA Ultimate Edition (version 2016.2.4)
    ✗ This install is older than the minimum recommended version of 2017.1.0.
[] VS Code (version 1.30.0)
[] Connected device (2 available)

! Doctor found issues in 1 category.

再度iOSアプリ実行

$ flutter clean
$ rm -rf ios/Podfile.lock
$ flutter run

さいごに

既存のFlutterプロジェクトをFlutter1系からFlutter2系にアップグレードしNull Safety移行しました。Androidは問題なく実行できましたが、iOSアプリは実行時にエラーが発生し対応が必要でした。CocoaPodsRubyのversionに気をつけてください。