#iOS14でのDatePickerの挙動について(SwiftUI)
前回書かせていただいたiOS14(UIKit)でのDatePickerに関してですが、ついでにSwiftUIでも調べたので書かせていただきました。
今回は従来のものから何が追加さたのかというところと実際の使い方のCodeも載せておきます。
環境
macOS Catalina 10.15.6
Xcode Version 12.0.1
はじめに
まずはじめにSwiftUIでのDatePickerの使い方から
struct ContentView: View {
@State private var selectionDate = Date()
var body: some View {
DatePicker("タイトル",
selection: $selectionDate)
}
}
これだけでDatePicerを使うことができます。
さすがSwiftUI!

デフォルトだとこんな感じです。
これだと流石に使い物にならんのでちょっと修正を加えます
struct ContentView: View {
@State private var selectionDate = Date()
var body: some View {
DatePicker("タイトル",
selection: $selectionDate)
// これを入れることによってラベルを表示させなくします。
.labelsHidden()
}
}

これで一旦検証はできそうです。
ちなみに別途Pickerの上にタイトルを入れたい場合
struct ContentView: View {
@State private var selectionDate = Date()
var body: some View {
VStack {
Text("タイトル")
.font(.title)
DatePicker("タイトル",
selection: $selectionDate)
.labelsHidden()
}
}
}

このようにすることでタイトルを付けれるようになります。
他にも良い実装はありますが今回は割愛します。
本題
では実際にSwiftUIではどのようにしてStyleやModeを変更するか確認します。
まずUIKitではenumで新しく定義されていました。
public enum UIDatePickerStyle : Int {
case automatic = 0
case wheels = 1
case compact = 2
@available(iOS 14.0, *)
case inline = 3
}
swiftUIではまずこのように定義してあります。
extension View {
/// Sets the style for date pickers within this view.
@available(tvOS, unavailable)
@available(watchOS, unavailable)
public func datePickerStyle<S>(_ style: S) -> some View where S : DatePickerStyle
}
使い方としましては、
DatePicker("タイトル", selection: $selectionDate)
.datePickerStyle(CompactDatePickerStyle())
このように定義することでStyleの変更ができます。
Style
公式ドキュメントを見るといくつかStyleがあります。
struct DefaultDatePickerStyle
struct CompactDatePickerStyle
struct WheelDatePickerStyle
struct FieldDatePickerStyle
struct StepperFieldDatePickerStyle
struct GraphicalDatePickerStyle
この中の
FieldDatePickerStyle
StepperFieldDatePickerStyle
この二つは macOS 10.15でのみ使えるとのことです。
iOS14で追加されたものは
GraphicalDatePickerStyle
になります。
DefaultDatePickerStyle
CompactDatePickerStyle
WheelDatePickerStyle
こちらの3つはiOS 13.0から追加されたものになります。
では実際の表示を確認してみます。
- DefaultDatePickerStyle

デフォルトだとこんな感じです。
動きはタップすると、カレンダーがポップアップします。
動き的にはUIKitと同じなので割愛します。
- CompactDatePickerStyle
こちらはdatePickerStyleだけ指定してもDefaultDatePickerStyleの挙動となんら変わりありません。
- WheelDatePickerStyle

こちらは従来通りのweelになります。
- GraphicalDatePickerStyle

こちらはデフォルトだとUIKitでもあった、圧縮されてしまう現象が起きています。
.frame
でいい感じに調整が必要です。
Mode
次にMode指定をしてみます。
DatePicker("タイトル", selection: $selectionDate, displayedComponents: .hourAndMinute)
displayedComponents
- .date
- .hourAndMinute
上記を指定できます。
DatePicker("タイトル", selection: $selectionDate, displayedComponents: .date)
.datePickerStyle(DefaultDatePickerStyle())
.labelsHidden()

DatePicker("タイトル", selection: $selectionDate, displayedComponents: .hourAndMinute)
.datePickerStyle(DefaultDatePickerStyle())
.labelsHidden()

上記の挙動としては
- DefaultDatePickerStyle
- CompactDatePickerStyle
共に同じ表示でした。
DatePicker("タイトル", selection: $selectionDate, displayedComponents: .date)
.datePickerStyle(WheelDatePickerStyle())
.labelsHidden()

DatePicker("タイトル", selection: $selectionDate, displayedComponents: .hourAndMinute)
.datePickerStyle(WheelDatePickerStyle())
.labelsHidden()

こちらに関してはやはり通常で、日にち表示なのか、時間表示なのかの違いでした。
DatePicker("タイトル", selection: $selectionDate, displayedComponents: .date)
.datePickerStyle(GraphicalDatePickerStyle())
.labelsHidden()

こちらに関してはTimeを消したとしてもやはり圧縮されてしまいます。

.frame(width: 300, height: 500)
フレーム指定してあげると、表示が正常になります。
が、サイズによってバグります(widthを400にしたらバグった)
これは使うのは厳しそうですね。。
DatePicker("タイトル", selection: $selectionDate, displayedComponents: .hourAndMinute)
.datePickerStyle(GraphicalDatePickerStyle())
.labelsHidden()

時間のみだと、カレンダーのTimeの部分だけ表示されるようになりました。
まとめ
今回はSwiftUIでの挙動を調べてみました。
使用する場合によってかもしれませんが、
GraphicalDatePickerStyleに関しては、UIKit同様バグというか表示に癖があるので、現段階ではどうしてもということがない限りあまり使わない方実装を考えた方が良さそうです。
正直あまり使わないかな〜とも思ったりもしてます。
まあ、宣言的にCodeをかけるのはやはりSwiftUIの強みだし、SwiftUIは書いてて楽しいので、
今後よくなることを期待して今回の調査を終えたいと思います。
次回はiOS14の位置情報の変更に関しての挙動でも書こうかと思います。
読んでいただきありがとうございました。
UIKit版はこちら
iOS14でのUIDatePickerの挙動について(UIKit)