EnvironmentValuesを制するものはSwiftUIを制する

# Environmentを制するものはSwiftUIを制する

## Environmentとは

> A dynamic view property that reads a value from the view’s environment.

いわゆる環境変数で、簡単にいうとViewを構成するための初期値みたいなものです。

早速簡単な例を見てみましょう。


```swift
struct ContentView: View {
    var body: some View {
        Text("Hello World")
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
            ContentView()
                .environment(\.font, .largeTitle)
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
        }
    }
}
```

![スクリーンショット 2019-09-06 12.21.50.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/e062de5d-9058-4d81-41f0-548ee8493874.png)

上記の例ではSwiftUIで`Font`を操作しています。`body`は非常にシンプルで

```swift
Text("Hello World")
```

変更では`Preview`の中で`.environment(\.font, .largeTitle)`を渡しているかどうかです。
これは外部から変数として与えてる例ですが、値をViewで読み込むには次のようになります。

```swift
struct ContentView: View {
    @Environment(\.font) var font: Font
    var body: some View {
        Text("Hello World")
    }
}
```

なんとかくイメージできましたかね？

## SwiftUIには多くのEnvironmentValuesが存在する

### var accessibilityDifferentiateWithoutColor: Bool

システム環境設定の「色を使わずに区別する」が有効になっているかどうか。これが有効な場合、UI は色だけで情報を伝えるのではなく、図形やグリフを使って情報を伝えるべきです。

### var accessibilityEnabled: Bool
> A Boolean value that indicates whether the user has enabled an assistive technology.

assistive（ユーザー支援）を行っているかのブール値。

### var accessibilityInvertColors: Bool

assistive（ユーザー支援）の色反転を使っているかのブール値。

### var accessibilityReduceMotion: Bool

システムの優先設定でモーションの軽減が有効になっているかどうか。このプロパティの値がtrueの場合、UIは大きなアニメーション、特に3次元をシミュレートするアニメーションを避けるべきです。


### var accessibilityReduceTransparency: Bool

透過性を減らすためのシステム環境設定を有効にしているかどうか。このプロパティの値が true の場合、UI (主にウィンドウ) の背景は半透明にしてはいけません。

### var allowsTightening: Bool
> A Boolean value that indicates whether inter-character spacing should tighten to fit the text into the available space.

使用可能なスペースにテキストを収めるために文字間スペースを狭めるかどうかを示すブール値。

### var calendar: Calendar
> The current calendar that views should use when handling dates.

ビューが日付を処理するときに使用する現在のカレンダー。

### var colorScheme: ColorScheme
> The color scheme of this environment.

この環境の配色。
ダークモードと通常モード

### var colorSchemeContrast: ColorSchemeContrast
> The contrast associated with the color scheme of this environment.

この環境の配色に関連するコントラスト。

### var controlActiveState: ControlActiveState

ビュー内のコントロールのアクティブな状態。

### var controlSize: ControlSize

ビュー内のコントロールに適用するサイズ。

### var defaultMinListHeaderHeight: CGFloat?
> The minimum height of a header in a list.

リスト内のヘッダーの最小の高さ。

### var defaultMinListRowHeight: CGFloat
> The default minimum height of a row in a list.

リスト内の行のデフォルトの最小の高さ。

### var defaultWheelPickerItemHeight: CGFloat
> The default height of an item in a wheel-style picker.

ホイールスタイルピッカーのアイテムのデフォルトの高さ。

### var description: String
不明

### var disableAutocorrection: Bool?

ビュー内のコントロールに適用するサイズ

### var displayScale: CGFloat
> The display scale of this environment.

この環境の表示スケール。

### var editMode: Binding<EditMode>?

これは次のチュートリアルにも出てきた。
__App Design and Layout Working with UI Controls__
https://developer.apple.com/tutorials/swiftui/working-with-ui-controls

### var font: Font?
> The default font of this environment.

この環境のデフォルトのフォント。

### var horizontalSizeClass: UserInterfaceSizeClass?
> The horizontal size class of this environment.

この環境の水平サイズクラス。

### var imageScale: Image.Scale
> The image scale for this environment.

この環境の画像スケール。

### var isEnabled: Bool
> A Boolean value that indicates whether the view associated with this environment allows user interaction.

この環境に関連付けられたビューがユーザーの操作を許可するかどうかを示すブール値。

### var layoutDirection: LayoutDirection
不明
おそらくレイアウトの方向

### var legibilityWeight: LegibilityWeight?
不明
おそらくこの辺りの話
__Text Size and Weight__
https://developer.apple.com/design/human-interface-guidelines/accessibility/overview/text-size-and-weight/

### var lineLimit: Int?
> The number of lines used to render text in the available space.

使用可能なスペースでテキストをレンダリングするために使用される行数。

### var lineSpacing: CGFloat

`Text`のlineSpacingのようだ

```swift
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
            ContentView()
                .environment(\.lineSpacing, 10)
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
        }
    }
}
```

![スクリーンショット 2019-09-06 13.04.49.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/fea856dd-6762-ce3d-65ec-37e54e66a880.png)
![スクリーンショット 2019-09-06 13.04.55.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/c59f8953-1af5-e73a-e249-027b4171f5d9.png)


### var locale: Locale
> The current locale that views should use.

ビューが使用する現在のロケール。

### var managedObjectContext: NSManagedObjectContext
不明

名前からの推測ではCoreDataを使った場合の`managedObjectContext`なんだろうと思う。

### var minimumScaleFactor: CGFloat
> The minimum permissible proportion to shrink the font size to fit the text into the available space.

テキストを使用可能なスペースに合わせるためにフォントサイズを縮小するための最小許容割合。

### var multilineTextAlignment: TextAlignment

`Text`の複数行でのAlignmentのようだ

```swift
struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        Group {
            ContentView()
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
            ContentView()
                .environment(\.multilineTextAlignment, .center)
                .previewDevice(PreviewDevice(rawValue: "iPhone XS Max"))
                .previewDisplayName("iPhone XS Max")
        }
    }
}
```

![スクリーンショット 2019-09-06 13.07.04.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/a9f0f31e-29de-c1a2-ada2-2be769545319.png)
![スクリーンショット 2019-09-06 13.07.14.png](https://qiita-image-store.s3.ap-northeast-1.amazonaws.com/0/80287/0b51ec0b-5c86-fcbd-0efa-0554049ecc29.png)


### var pixelLength: CGFloat
> The size of a pixel on the screen.

画面上のピクセルのサイズ。

### var presentationMode: Binding<PresentationMode>

```swift
/// The mode of a view indicating whether it is currently presented by another
/// view.
@available(iOS 13.0, OSX 10.15, tvOS 13.0, watchOS 6.0, *)
public struct PresentationMode {

    /// Indicates whether a view is currently presented.
    public var isPresented: Bool { get }

    /// Dismisses the view if it is currently presented.
    ///
    /// If `isPresented` is false, `dismiss()` is a no-op.
    public mutating func dismiss()
}
```

`sheet`などで遷移した次のViewにBindingの変数を渡さずとも、`EnvironmentValues`から取得可能。

```swift
@Environment(\.presentationMode) var presentationMode: Binding<PresentationMode>
```

遷移した画面を閉じることができる。

```swift
self.presentationMode.wrappedValue.dismiss()
```

### var sizeCategory: ContentSizeCategory
不明

### var timeZone: TimeZone
> The current time zone that views should use when handling dates.

ビューが日付を処理するときに使用する現在のタイムゾーン。

### var truncationMode: Text.TruncationMode
> A value that indicates how the layout truncates the last line of text to fit into the available space.

使用可能なスペースに収まるようにレイアウトがテキストの最後の行を切り捨てる方法を示す値。

### var undoManager: UndoManager?
> The undo manager that views should use to register undo operations.

ビューが取り消し操作を登録するために使用する取り消しマネージャー。

### var verticalSizeClass: UserInterfaceSizeClass?
> The vertical size class of this environment.

この環境の垂直サイズクラス。

---

## EnvironmentValuesはカスタマイズ可能

自分でEnvironmentValuesを定義することもできる。

__不明なところがあるので情報お持ちの方編集リクエストください！__