SwiftUIにおけるViewの縦横判定


一般的にcompact/regularで判断付けていた気がするけれど。

https://developer.apple.com/design/human-interface-guidelines/layout/

## 前提
widthをw、heightをhと表す。
compactをC、regularをRと表す。

## compact/regularのまとめ
iPhoneが**縦向き**の場合、全てwChRである。
iPhoneの*横向き*の場合、全てhCである。

iPadはフルスクリーン時において、*縦向き*、**横向き**、全てwRhRである。
iPadが*縦向き*でsplit viewを使う場合、全てwChRである。
iPadは2/3 split viewの場合、**横向き**は全てwRhRである。
それ以外のsplit viewは全てwChRである。

したがって、iPadの場合「縦か横か」を判定するためにSizeClassが使えない（レイアウトの振り分けには使えるけれど）

## Notificationを使う
単純な縦横を知りたいだけならば次のモディファイアを足す。
```Swift
.onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { output in
            guard let device = output.object as? UIDevice else { return }
            // device.orientation.isPortrait のtrue / falseで判断つく
        }
```

## 検証用ソース

```Swift
struct ContentView: View {
    
    var iPhoneLandscape : some View {
        Text("iPhone Landscape")
    }
    
    var iPhonePortrait : some View {
        Text("iPhone Portrait")
    }
    
    var iPadLandscape : some View {
        Text("iPad Landscape")
    }
    
    var iPadPortrait : some View {
        Text("iPad Portrait")
    }
    
    var main: some View {
        VStack {
            switch deviceSize {
            case .wChR:
                Text("wChR")
            case .wRhR:
                Text("wRhR")
            case .wChC:
                Text("wChC")
            case .wRhC:
                Text("wRhC")
            }
            
            switch device {
            case .pad:
                if isPortrait {
                    iPadPortrait
                } else {
                    iPadLandscape
                }
            case .phone:
                if isPortrait {
                    iPhonePortrait
                } else {
                    iPhoneLandscape
                }
                // 他の端末は何もしない
            case .unspecified, .tv, .carPlay, .mac:
                EmptyView()
            @unknown default:
                EmptyView()
            }
        }
    }
    
    enum DeviceSize {
        case wRhR
        case wRhC
        case wChR
        case wChC
    }
    
    // iPadかiPhoneか
    let device = UIDevice.current.userInterfaceIdiom
    // 横向きか縦向きか
    @State private var isPortrait: Bool = UIDevice.current.orientation.isPortrait
    
    // compact/regular
    @Environment(\.horizontalSizeClass) private var horizontalSizeClass
    @Environment(\.verticalSizeClass) private var verticalSizeClass
    
    var deviceSize: DeviceSize {
        guard let horizontalSizeClass , let verticalSizeClass else {
            return .wRhR
        }
        switch (horizontalSizeClass, verticalSizeClass) {
        case (.regular, .regular):
            return .wRhR
        case (.regular, .compact):
            return .wRhC
        case (.compact, .regular):
            return .wChR
        case (.compact, .compact):
            return .wChC
        default:
            return .wRhR
        }
    }
    
    
    var body: some View {
        main
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { output in
            guard let device = output.object as? UIDevice else { return }
            self.isPortrait = device.orientation.isPortrait
        }
    }
}
```