SwiftUI Xcode Previews あるあるエラー5選

# はじめに
XcodePreviews によって View をプレビューさせるときのエラーは確認方法が特殊です。
まず、 Xcode 右下に表示されるコンソールには表示されません。

そこで、今回は5つに絞ってそのエラーの確認方法・解決策をご紹介します。
エンジニアはプレビューの仕組みに振り回されるのではなく、プロダクト開発自体に集中すべきです。ぜひ、「へぇ、こんなこともあるんだ」と思っていただき、「あ！これあのときのやつだ！」と思い出せるきっかけにしていただければと思います。

## Lv. 1 No Buildable Entries Error
```md
HumanReadableSwiftError

CreationError: noBuildExecutor
---------------------------------------------------------------
NoBuildableEntriesError: active scheme does not build this file

Select a scheme that builds a target which contains the current file, or add this file to a target that is built by the current scheme.
```
`PreviewProvider` に準拠した構造体が定義されている場所が、現在選択されている Scheme と異なる場合に表示されるエラーです。エラーも親切で比較的わかりやすいと思われます。


## Lv. 2 Remote Human Readable Error
```md
RemoteHumanReadableError: Failed to update preview.

The preview process appears to have crashed.

Error encountered when sending 'render' message to agent.

==================================

|  RemoteHumanReadableError: The operation couldn’t be completed. (BSServiceConnectionErrorDomain error 3.)
|  
|  BSServiceConnectionErrorDomain (3):
|  ==BSErrorCodeDescription: OperationFailed
```
アプリが起動できないときに表示されるエラーです。 Xcode Previews で実行される処理には限りがあるため、 AutoLayout にミスがある場合に遭遇することが多いエラーのように感じます（Live Preview, Debug Preview 時にはもっと原因の可能性が広がります）。

これ以上の原因はエラーログを見る必要があります。`~/Library/Logs/DiagnosticReports` に `.crash` という拡張子でクラッシュログファイルが出力されます。以下が参考例です。

```md
Application Specific Information:
*** Terminating app due to uncaught exception 'NSGenericException', reason: 'Unable to activate constraint with anchors <NSLayoutYAxisAnchor:0x6000022bf700 "UITableView:0x7fdfcd020c00.top"> and <NSLayoutYAxisAnchor:0x6000022bf4c0 "UIView:0x7fdfda506c70.bottom"> because they have no common ancestor.  Does the constraint or its anchors reference items in different view hierarchies?  That's illegal.'
terminating with uncaught exception of type NSException
abort() called
CoreSimulator 732.18.6 - Device: iPhone SE (2nd generation) (03...77) - Runtime: iOS 14.3 (18C61) - DeviceType: iPhone SE (2nd generation)
```

注目すべきは `Application Specific Information:` という項目になります。レイアウト処理にミスがあった場合に上記のようなログが出力されます。
上記ログからどんなミスが考えられるでしょうか。今回は対象の View を addSubview せずに AutoLayout で制約をつけるコードを書いて再現してみました。

## Lv. 3 Compiling failed: extra argument in call
```md
extra argument in call

----------------------------------------

CompileDylibError: Failed to build ComponentsPreviews.swift

Compiling failed: extra argument in call

/Users/akkeylab/Development/akkey-ios/AkkeyPreviews/Classes/ComponentsPreviews.swift:54:17: error: extra argument in call
                StackableTagListView()
                ^~~~~~~~~~~~~~~~~~~~
```
```swift
struct ComponentsPreviews: PreviewProvider {
    static var previews: some View {
        Group {
            .... < ---- Max 10
        }
    }
}
```

`Group` に渡す View の数が10個を超えると発生するビルドエラーです。もちろんプレビューできません。
回避策ですが、 `Group` を入れ子構造で増やしていけばある程度増やせます（おすすめしません）。

## Lv. 4 Showing 15 of 16 previews
```md
Showing 15 of 16 previews

The maximum number of previews pre `PreviewProvider` is 15.
```
これは一部に表示されるエラーになります。プレビュー領域下部にひっそり表示されますので気づいてあげてください。
PreviewProvider に準拠した構造体1つに対してプレビューできる View の個数は15個までという制約があります。この制限を超えた時、表示されるエラーです。

回避策ですが、 PreviewProvider に準拠した構造体を量産することで理論上無限に増やせます（おすすめしません）。つまり、この制約は1つのプレビュー画面に表示できる View の個数というわけではないのです。
TableView で例えるなら1セクションに入れられるセルの数が15個で、セクションを増やせば1つの TableView で表示できるセルの数は無限にできる　といった感じでしょうか。

## Lv. 5 linker command failed with exit code 1
```md
linker command failed with exit code 1 (use -v to see invocation)

----------------------------------------

failedToBuildDylib: ld: warning: directory not found for option '-F/Applications/Xcode.app/Contents/SharedFrameworks-iphonesimulator'
Undefined symbols for architecture x86_64:
  "___llvm_profile_runtime", referenced from:
      ___llvm_profile_runtime_user in FirebaseCore(FIRAppAssociationRegistration.o)
      ___llvm_profile_runtime_user in FirebaseCore(FIRComponentType.o)
      ___llvm_profile_runtime_user in FirebaseCore(FIRConfiguration.o)
      ___llvm_profile_runtime_user in FirebaseCore(FIRCoreDiagnosticsConnector.o)
      ___llvm_profile_runtime_user in FirebaseCore(FIRDiagnosticsData.o)
      ___llvm_profile_runtime_user in FirebaseCore(FirebaseCore-dummy.o)
      ___llvm_profile_runtime_user in FirebaseCore(FIRComponentContainer.o)
      ...
     (maybe you meant: ___llvm_profile_runtime_user)
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)
```
[Undefined symbols ___llvm_profile_runtime](https://stackoverflow.com/questions/58127940/undefined-symbols-llvm-profile-runtime)
[SwiftUI 導入で LLVM のドキュメント読む羽目になった話](https://qiita.com/AkkeyLab/items/a698545f2423b9b1dec9)
[【続編】SwiftUI 導入で LLVM のドキュメント読む羽目になった話](https://qiita.com/AkkeyLab/items/4dea648b67b6998c5019)

リンカーコマンドの実行に失敗したときに表示されるエラーです。エラー内容からわかることも多いですが、対応方針の模索に苦戦することが多いように思います。
上記エラー例はプロジェクトのカバレッジを有効にしていた場合に特定条件下で発生するものです。詳しくは上記参考リンクより御覧ください。

# おわりに
いかがだったでしょうか。
「いやいや、あるあるじゃないでしょｗ」「結構一般常識？」「これは勉強になりました！」
といろいろな声が聞こえてきそうです。ぜひ皆さんの感想を教えて下さい！