Flutter開発環境を更新したらいろいろとハマったこと

# はじめに
プライベートで作っているアプリ(私用iPhoneのみに入れて使用、ストア公開などはしていない)を長らく放置していたので、諸々更新してみた。

# 環境
| 種別 | 旧環境 | 新環境 |
|:-----------|:------------|:------------|
| 端末       | MacBook Pro (13-inch, 2017)        | MacBook Pro (14-inch, 2021)         |
| OS     | macOS BigSur      | macOS Monterey       |
| IDE     | AndroidStudio 4.2.2      | AndroidStudio Arctic Fox 2020.3.1 Patch 4      |
| flutter     | 2.2.3      | 2.8.0       |
| dart     | 2.12.0      | 2.15.0       |
半年以上放置していたのでflutter/dartのバージョンの乖離がなかなか大きいが、2021年12月時点の最新版に上げることを目標とする。


# やったこと
## 端末・IDE
新端末が届いたら、とりあえずTimeMachineから中身をそのままリストア。
Android Studioを開くと、更新があるとのことで言われるままに最新版をインストール。

結果:
![image.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/29025/6e0fbcca-74c6-0a01-ba73-738f2a3cee90.png)

この時点で一旦、iOS Simulatorを起動して、アプリが動くか確認してみる。

```terminal
../../.pub-cache/hosted/pub.dartlang.org/flutter_datetime_picker-1.5.1/lib/flutter_datetime_picker.dart:311:32: Warning: Operand of null-aware operation '??' has type 'Color' which excludes null.
 - 'Color' is from 'dart:ui'.
                  color: theme.backgroundColor ?? Colors.white,
```
使用している[flutter_datetime_picker](https://pub.dev/packages/flutter_datetime_picker)周りで何やら警告が出たが、意外にもちゃんと起動した。

## flutter/dart/ライブラリの更新
バージョン管理には[fvm](https://github.com/leoafarias/fvm)を利用しているので、fvmコマンドから更新する。

```terminal
# 利用可能なバージョンを確認
% fvm releases  
(中略)
--------------------------------------
Dec 9 21   │ 2.8.0             stable
--------------------------------------
% fvm install 2.8.0                                                                                                                                                                                                                                                                                                                                                
Unhandled exception:
Bad state: Future already completed
#0      _AsyncCompleter.complete (dart:async/future_impl.dart:43:31)
#1      _NativeSocket.startConnect.<anonymous closure>.connectNext.<anonymous closure> (dart:io-patch/socket_patch.dart:682:23)
#2      _NativeSocket.issueWriteEvent.issue (dart:io-patch/socket_patch.dart:1102:14)
#3      _NativeSocket.issueWriteEvent (dart:io-patch/socket_patch.dart:1109:12)
#4      _NativeSocket.multiplex (dart:io-patch/socket_patch.dart:1130:11)
#5      _RawReceivePortImpl._handleMessage (dart:isolate-patch/isolate_patch.dart:168:12).
Attempt:11 waiting for isolate vm-isolate to check in
Attempt:11 waiting for isolate dartdev to check in
Attempt:12 waiting for isolate vm-isolate to check in
Attempt:12 waiting for isolate dartdev to check in
Attempt:13 waiting for isolate vm-isolate to check in
Attempt:13 waiting for isolate dartdev to check in
...
```
どうやらfvm自体のバージョンが古いせいか、何やらうまくいかない。
[マニュアル](https://fvm.app/docs/getting_started/installation/)によるとHomebrewからインストールできるようになったようなので、一旦消して入れ直す。

```terminal
% brew install fvm
==> Downloading https://github.com/leoafarias/fvm/archive/2.2.5.tar.gz
==> Downloading from https://codeload.github.com/leoafarias/fvm/tar.gz/2.2.5
######################################################################## 100.0%
==> Installing fvm from leoafarias/fvm
==> /usr/local/opt/dart/libexec/bin/dart pub get
==> /usr/local/opt/dart/libexec/bin/dart compile exe -Dversion=2.2.5 bin/main.dart -o fvm
🍺  /usr/local/Cellar/fvm/2.2.5: 6 files, 6.7MB, built in 18 seconds
==> Running `brew cleanup fvm`...
Disable this behaviour by setting HOMEBREW_NO_INSTALL_CLEANUP.
Hide these hints with HOMEBREW_NO_ENV_HINTS (see `man brew`).
% fvm --version
2.2.5
% fvm install 2.8.0
Flutter "2.8.0" is not installed.

Installing version: 2.8.0...
Cloning into '/Users/xxx/fvm/versions/2.8.0'...
remote: Enumerating objects: 349488, done.        
remote: Total 349488 (delta 0), reused 0 (delta 0), pack-reused 349488        
Receiving objects: 100% (349488/349488), 172.73 MiB | 5.16 MiB/s, done.
Resolving deltas: 100% (268470/268470), done.
HEAD is now at cf44000065 'Update Engine revision to 40a99c595137e4b2f5b2efa8ff343ea23c1e16b8 for stable release 2.8.0' (#94889)
Downloading Dart SDK from Flutter engine 40a99c595137e4b2f5b2efa8ff343ea23c1e16b8...
  % Total    % Received % Xferd  Average Speed   Time    Time     Time  Current
                                 Dload  Upload   Total   Spent    Left  Speed
100  205M  100  205M    0     0  9717k      0  0:00:21  0:00:21 --:--:-- 9836k
Building flutter tool...
Flutter 2.8.0 • channel stable • https://github.com/flutter/flutter.git
Framework • revision cf44000065 (3 days ago) • 2021-12-08 14:06:50 -0800
Engine • revision 40a99c5951
Tools • Dart 2.15.0
% fvm use 2.8.0
Project now uses Flutter [2.8.0]
```
これでプロジェクト内のfvm_config.jsonが自動的に更新される。

```json
{
  "flutterSdkVersion": "2.8.0",
  "flavors": {}
}
```
一旦ダメ元でこの状態でSimulator起動を試みる。

```terminal
Failed to build iOS app
Error output from Xcode build:
↳
    2021-12-12 17:00:31.661 xcodebuild[55796:1477321]  DVTAssertions: Warning in /Library/Caches/com.apple.xbs/Sources/DVTiOSFrameworks/DVTiOSFrameworks-19450/DTDeviceKitBase/DTDKRemoteDeviceData.m:373
    Details:  (null) deviceType from 00008030-0015312826D0402E was NULL when -platform called.
    Object:   <DTDKMobileDeviceToken: 0x1300d2e20>
    Method:   -platform
    Thread:   <NSThread: 0x600002d14640>{number = 5, name = (null)}
    Please file a bug at https://feedbackassistant.apple.com with this warning message and any useful information you can provide.
    2021-12-12 17:00:31.841 xcodebuild[55796:1477312]  DVTAssertions: Warning in /Library/Caches/com.apple.xbs/Sources/DVTiOSFrameworks/DVTiOSFrameworks-19450/DTDeviceKitBase/DTDKRemoteDeviceData.m:373
    Details:  (null) deviceType from 00008030-0015312826D0402E was NULL when -platform called.
    Object:   <DTDKMobileDeviceToken: 0x1300d2e20>
    Method:   -platform
    Thread:   <NSThread: 0x600002255a40>{number = 2, name = (null)}
    Please file a bug at https://feedbackassistant.apple.com with this warning message and any useful information you can provide.
    2021-12-12 17:00:31.932 xcodebuild[55796:1477312]  DVTAssertions: Warning in /Library/Caches/com.apple.xbs/Sources/DVTiOSFrameworks/DVTiOSFrameworks-19450/DTDeviceKitBase/DTDKRemoteDeviceData.m:373
    Details:  (null) deviceType from 00008030-0015312826D0402E was NULL when -platform called.
    Object:   <DTDKMobileDeviceToken: 0x1300d2e20>
    Method:   -platform
    Thread:   <NSThread: 0x600002255a40>{number = 2, name = (null)}
    Please file a bug at https://feedbackassistant.apple.com with this warning message and any useful information you can provide.
    ** BUILD FAILED **
```
何やらいろいろ怒られる。
こういうときはとりあえずclean。

```terminal
% fvm flutter clean                                                                                                                                                                                                                                                                                                                                                (git)-[main]
Cleaning Xcode workspace...                                         3.7s
Deleting build...                                                  570ms
Deleting .dart_tool...                                              21ms
Deleting .packages...                                                0ms
Deleting Generated.xcconfig...                                       0ms
Deleting flutter_export_environment.sh...                            0ms
Deleting Flutter.framework...                                        2ms
Deleting Flutter.podspec...                                          0ms
Deleting .flutter-plugins-dependencies...                            0ms
Deleting .flutter-plugins...                                         0ms
```
もう1回ビルド。

```terminal
Launching lib/main.dart on iPhone 13 in debug mode...
Running pod install...
Running Xcode build...
Xcode build done.                                           74.6s
Failed to build iOS app
Error output from Xcode build:
↳
    ** BUILD FAILED **
(中略)
warning: The iOS Simulator deployment target 'IPHONEOS_DEPLOYMENT_TARGET' is set to 8.0, but the range of supported deployment target versions is 9.0 to 15.0.99.
```

大量に警告が出てしまったが、とりあえずわかりやすい一番最後の警告に対処するため、Podfileを以下のように更新。

```
    post_install do |installer|
      installer.pods_project.targets.each do |target|
        flutter_additional_ios_build_settings(target)
        target.build_configurations.each do |config|
          config.build_settings['IPHONEOS_DEPLOYMENT_TARGET'] = '9.0' #ここを追加
        end
      end
    end
```

ライブラリ周りの警告はそのまま。とりあえずえいやで更新を試みる、

```terminal
% fvm flutter pub outdated
% fvm flutter pub upgrade
% fvm flutter pub upgrade --major-versions
```

何やらまた違ったエラーが発生。

```terminal
Launching lib/main.dart on iPhone 13 in debug mode...
Running pod install...
CocoaPods' output:
↳
      Preparing

    Analyzing dependencies

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

    Finding Podfile changes
      - Flutter
      - cloud_firestore
      - firebase_auth
      - firebase_core

    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 '8.9.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_auth` from `.symlinks/plugins/firebase_auth/ios`
    firebase_auth: Using Firebase SDK version '8.9.0' defined in 'firebase_core'
    -> Fetching podspec for `firebase_core` from `.symlinks/plugins/firebase_core/ios`
    firebase_core: Using Firebase SDK version '8.9.0' defined in 'firebase_core'

    Resolving dependencies of `Podfile`
      CDN: trunk Relative path: CocoaPods-version.yml exists! Returning local because checking is only performed in repo update
      CDN: trunk Relative path: all_pods_versions_0_3_5.txt exists! Returning local because checking is only performed in repo update
      CDN: trunk Relative path: Specs/0/3/5/Firebase/8.9.1/Firebase.podspec.json exists! Returning local because checking is only performed in repo update
      CDN: trunk Relative path: Specs/0/3/5/Firebase/8.9.0/Firebase.podspec.json exists! Returning local because checking is only performed in repo update
    [!] CocoaPods could not find compatible versions for pod "Firebase/Firestore":
      In snapshot (Podfile.lock):
        Firebase/Firestore (= 8.3.0)

      In Podfile:
        cloud_firestore (from `.symlinks/plugins/cloud_firestore/ios`) was resolved to 3.1.4, which depends on
          Firebase/Firestore (= 8.9.0)


    You have either:
     * out-of-date source repos which you can update with `pod repo update` or with `pod install --repo-update`.
     * changed the constraints of dependency `Firebase/Firestore` inside your development pod `cloud_firestore`.
       You should run `pod update Firebase/Firestore` to apply changes you've made.
(以下略)
```

使用している`firebase_auth`の依存性に問題がある模様。`firebase_auth: ^3.3.3`に更新し、`pod update`をしてみる。

```terminal
% pod update Firebase/Firestore
Updating local specs repositories
Analyzing dependencies
cloud_firestore: Using Firebase SDK version '8.9.0' defined in 'firebase_core'
firebase_auth: Using Firebase SDK version '8.9.0' defined in 'firebase_core'
firebase_core: Using Firebase SDK version '8.9.0' defined in 'firebase_core'
Downloading dependencies
Installing BoringSSL-GRPC (0.0.7)
Installing Firebase (8.9.0)
Installing FirebaseAuth (8.9.0)
Installing FirebaseCore (8.9.0)
Installing FirebaseCoreDiagnostics (8.10.0)
Installing FirebaseFirestore (8.9.1)
Installing Flutter (1.0.0)
Installing GTMSessionFetcher (1.7.0)
Installing GoogleDataTransport (9.1.2)
Installing GoogleUtilities (7.6.0)
Installing PromisesObjC (2.0.0)
Installing abseil (0.20200225.0)
Installing cloud_firestore (3.1.4)
Installing firebase_auth (3.3.3)
Installing firebase_core (1.10.5)
Installing gRPC-C++ (1.28.2)
Installing gRPC-Core (1.28.2)
Installing leveldb-library (1.22.1)
Installing nanopb (2.30908.0)
Generating Pods project
Integrating client project
Pod installation complete! There are 4 dependencies from the Podfile and 19 total pods installed.
```

更に、[Stack Overflow](https://stackoverflow.com/questions/68366355/flutter-ios-app-runs-on-xcode-but-wont-run-on-vscode-and-android-studio)の投稿を参考に、XcodeからRunnerの設定を修正すると、Riverpod周り以外のエラーはほぼ消えたように見える。
Riverpodについては[こちら](https://zenn.dev/riscait/books/flutter-riverpod-practical-introduction/viewer/migrate-to-v1#useprovider-%E3%81%8C%E5%89%8A%E9%99%A4%E3%81%95%E3%82%8C%E3%81%BE%E3%81%97%E3%81%9F)の記事を参考に、HookConsumerWidgetに書き換えたらエラーは雲散霧消した。

ビルドエラーは解決したと思ったら、シミュレータで起動しない。

```terminal
Unable to install /Users/xxx/build/ios/iphonesimulator/Runner.app on 449EA47A-7C4E-4FE6-B548-4BB12267C703. This is sometimes caused by a malformed plist file:
ProcessException: Process exited abnormally:
An error was encountered processing the command (domain=NSPOSIXErrorDomain, code=22):
Failed to install the requested application
The application's Info.plist does not contain a valid CFBundleVersion.
Ensure your bundle contains a valid CFBundleVersion.
  Command: /usr/bin/arch -arm64e xcrun simctl install 449EA47A-7C4E-4FE6-B548-4BB12267C703 /app-path/build/ios/iphonesimulator/Runner.app
Error launching application on iPhone 13.
```

Info.plistのCFBundleVersionがおかしいとのこと。以下の値に変更。

```
	<key>CFBundleVersion</key>
	<string>$(CURRENT_PROJECT_VERSION)</string>
```

結果、シミュレータで起動したので、実機リリースも敢行！

# おわりに
Info.plist周りは少し詰まったが、全体として思ったほど問題は出ずに更新作業は完了した。
ただ、既存のものを変えずにバージョンだけ追随する形になっているので、Flutter自体の新機能などはまた追っていきたい所存。