SwiftUIにおけるPresenting Additional Views の基本


Presenting Additional ViewsとはApple公式で提供されているSwiftUIにおける基本Viewへの追加Viewです。
よくモーダルなどと表現されるものです。
今までのUIKitでは、addSubViewやpresentなどを駆使して表示されていた追加Viewはここに集約されていくと思い、調べて見ました。

[SwiftUI - view](https://developer.apple.com/documentation/swiftui/view)

Twiiterの投稿ボタンをタップし、表示される投稿画面などが主な使われ方かなと思います。

![ダウンロード.gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55864/168a3db2-cd78-b7f3-5fee-bc7aef21a188.gif)


また、@H_Crane さんの書いてる[SwiftUIのチートシート](https://qiita.com/H_Crane/items/eb847ca7fb7a0b9e8073)に刺激を受けて、まとめてみました。



# 動作環境

- Xcode 11.2.1
- macOS Catalina ver 10.15.2

# 4種類のPresenting Additional Views

公式で提供されているPresenting Additional Viewsは4種類あります。順を追って見ていきましょう

- Sheet
- ActionSheet
- Alert
- Popover

## Sheet

Sheetは基本的なPresenting Additional Viewの基本の中でもっともカスタムで可能なViewです。
下記、SwiftUIでButtonを押した時に表示される例です。
`Text("This is Sheet.")`と言う箇所がViewのカスタム内容となっており、こちらの中に他で定義したViewクラスを呼び出すことも可能です。

```swift
    Button(action: {
        self.showSheet.toggle()
    }, label: {
        Text("AddSheet")
    }).sheet(isPresented: self.$showSheet, content: {
        Text("This is Sheet.")
    })
```

![ダウンロード (1).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55864/305aba80-2ead-4d56-c349-9e513a8cf752.gif)


[Sheet公式](https://developer.apple.com/documentation/swiftui/view/3352791-sheet)

## ActionSheet

ActionSheetはユーザーに選択肢から選ばせるViewです。
UIKitでは`UIAlertController` で実現していたものですね。
`UIAlertController`とほぼ動作が変わらないので同じノリで利用できそうです。

```swift
    Button(action: {
        self.showActionSheet.toggle()
    }, label: {
        Text("AddActionSheet")
    }).actionSheet(isPresented: self.$showActionSheet, content: {
        ActionSheet(title: Text("Action"),
            message: Text("Description"),
            buttons: [
                .default(Text("OK"), action: {

                }),
                .destructive(Text("Delete"), action: {

                })
            ]
        )
    })
```

![ダウンロード (2).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55864/971a2c83-e236-eea8-00ca-ea00f5e7e6a6.gif)


[ActionSheet公式](https://developer.apple.com/documentation/swiftui/view/3352685-actionsheet)

## Alert

Alertはユーザーへメッセージを通知するViewです。
UIKitでは`UIAlertController` で実現していたものですね。
こちらもActionSheetと同じように `UIAlertController`とほぼ動作が変わらないので同じノリで利用できそうです。

```swift
    Button(action: {
        self.showAlert.toggle()
    }, label: {
        Text("AddAlert")
    }).alert(isPresented: self.$showAlert, content: {
        Alert(title: Text("Error"), message: Text("Error Reason"), dismissButton: .default(Text("OK")))
    })
```

![ダウンロード (3).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55864/91b775c5-c4b3-fc6b-9296-f4707e3bcbec.gif)


[Alert公式](https://developer.apple.com/documentation/swiftui/view/3352687-alert)

## Popover

PopoverはSheetと同じようにカスタムができるViewなのですが、違いがわからず、実行して触って見ても下記のような不明な動作をしました。
![ダウンロード (4).gif](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/55864/2db0f8d8-00d3-cce5-e250-90d5f0f9906f.gif)


```swift
    Button(action: {
        self.showPopOver.toggle()
    }, label: {
        Text("AddPopOver")
    }).popover(isPresented: self.$showPopOver, attachmentAnchor: .rect(.bounds), arrowEdge: .leading, content: {
        Text("This is PopOver.")
    })
```

一体、何のためのViewなのだろうとデザインガイドラインを調べたところ下記のような表記がありました。

> Avoid displaying popovers on iPhones. Generally, popovers should be reserved for use in iPad apps. In iPhone apps, utilize all available screen space by presenting information in a full-screen modal view, rather than in a popover. For related guidance, see Modality.

つまりiPadやMacのViewということですね。Sheetを使いましょう。

[デザインガイドライン - popover](https://developer.apple.com/design/human-interface-guidelines/ios/views/popovers/)


# まとめ

- カスタムはSheet/選択させたい場合はAction/メッセージはAlertを利用する
- PopoverはiPhone開発では利用しない

今回のサンプルコードを下記に置きました。今後も調べた内容を試していくので、スターなどいただけるとありがたいです⭐️

[SampleViewSwiftUI](https://github.com/entaku19890818/SampleViewSwiftUI)