はじめに
本記事は iOS Advent Calendar 2020 の10日目の記事です。
昨日は @417_72ki さんで SwiftのKeyPathと戯れる でした。
iOS 14で追加されたWidgetのオススメPreviewを紹介します。
環境
- OS:macOS Big Sur 11.0.1
- Xcode:12.2 (12B45b)
- Swift:5.3.1
対象コード
対象WidgetのEntryViewとEntryのコードを載せます。
長いので折りたたみにします。
本筋ではないので読み飛ばしても構いません。
EntryViewのコード
import WidgetKit
import SwiftUI
struct MonsterEntryView: View {
var entry: MonsterWidget.Provider.Entry
@Environment(\.widgetFamily) private var family
var body: some View {
switch family {
case .systemSmall:
ZStack {
Color(.systemBackground)
VStack {
icon
Spacer(minLength: 8.0)
name
}
.padding()
}
case .systemMedium:
ZStack {
Color(.systemBackground)
HStack {
VStack {
icon
Spacer(minLength: 8.0)
name
}
Spacer(minLength: 16.0)
description
}
.padding()
}
case .systemLarge:
EmptyView()
@unknown default:
EmptyView()
}
}
private var icon: some View {
Image(uiImage: entry.icon)
.resizable()
.aspectRatio(contentMode: .fit)
}
private var name: some View {
Text(entry.name)
.font(.headline)
}
private var description: some View {
Text(entry.description)
.font(.body)
}
}
Entryのコード
struct MonsterWidget: Widget { ... }
extension MonsterWidget {
struct Entry: TimelineEntry {
let date: Date
let name: String
let description: String
let icon: UIImage
static func createDefault() -> Entry {
.init(
date: Date(),
name: "uhooi",
description: "ゆかいな みどりの せいぶつ。\nわるそうに みえるが むがい。",
icon: UIImage(named: "Uhooi")!
)
}
}
}
Previewに不要なWidgetとProviderのコードは省略します。
参考リンクにあるウホーイ図鑑のコードをご参照ください。
WidgetのオススメPreview一覧
WidgetのオススメPreview一覧を紹介します。
プレースホルダー
プレースホルダーの表示をプレビューします。
EntryViewに .redacted(reason: .placeholder)
を付けると、プレースホルダーで表示します。
コード
struct MonsterEntryView_Previews: PreviewProvider {
static var previews: some View {
// プレースホルダー
MonsterEntryView(entry: .createDefault())
.redacted(reason: .placeholder) // !!!
.previewContext(WidgetPreviewContext(family: .systemSmall)) // Mediumの場合は `.systemMedium` を指定する
}
}
}
プレビュー
Small | Medium |
---|---|
通常
通常の表示をプレビューします。
プレースホルダーのプレビューから .redacted(reason: .placeholder)
を取り除くのみです。
コード
struct MonsterEntryView_Previews: PreviewProvider {
static var previews: some View {
// 通常
MonsterEntryView(entry: .createDefault())
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
}
プレビュー
Small | Medium |
---|---|
ダークモード
ダークモードの表示をプレビューします。
通常のプレビューに .environment(\.colorScheme, .dark)
を付けるのみです。
コード
struct MonsterEntryView_Previews: PreviewProvider {
static var previews: some View {
// ダークモード
MonsterEntryView(entry: .createDefault())
.environment(\.colorScheme, .dark) // !!!
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
}
プレビュー
Small | Medium |
---|---|
短い文字列
短い文字列の表示をプレビューします。
Previewを使うと境界値の表示もかんたんに確認できます。
コード
struct MonsterEntryView_Previews: PreviewProvider {
typealias Entry = MonsterWidget.Entry
static var previews: some View {
// 短い文字列
MonsterEntryView(entry: createShortEntry())
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
private static func createShortEntry() -> Entry {
.init(
date: Date(),
name: "1",
description: "1",
icon: UIImage(named: "Uhooi")!
)
}
}
プレビュー
Small | Medium |
---|---|
Mediumで 1
が右寄せなのが気になります。
おそらく HStack
と Spacer()
を使えば左寄せにできますが、短い文字列が入ることを想定していないので、このままとしています。
長い文字列
長い文字列の表示をプレビューします。
短い文字列と同様の方法です。
コード
struct MonsterEntryView_Previews: PreviewProvider {
typealias Entry = MonsterWidget.Entry
static var previews: some View {
// 長い文字列
MonsterEntryView(entry: createLongEntry())
.previewContext(WidgetPreviewContext(family: .systemSmall))
}
}
private static func createLongEntry() -> Entry {
.init(
date: Date(),
name: "123456789012345678901234567890",
description: "12345678901234567890\n12345678901234567890\n12345678901234567890",
icon: UIImage(named: "Uhooi")!
)
}
}
プレビュー
Small | Medium |
---|---|
Small・Mediumの両方で画像が小さくなるのが気になりますが、モンスター名が長くなることを想定していないので、このままとしています。
「…」になるのも気になりますが、同様の理由でこのままとしています。
全体図
上記のコードをいい感じにまとめました。
struct MonsterEntryView_Previews: PreviewProvider {
typealias Entry = MonsterWidget.Entry
static var previews: some View {
ForEach(families.indices) { index in
previewEntryViewGroup
.previewContext(WidgetPreviewContext(family: families[index]))
}
}
private static let families: [WidgetFamily] = [.systemSmall, .systemMedium]
private static var previewEntryViewGroup: some View {
Group {
MonsterEntryView(entry: .createDefault())
.redacted(reason: .placeholder)
MonsterEntryView(entry: .createDefault())
MonsterEntryView(entry: .createDefault())
.environment(\.colorScheme, .dark)
MonsterEntryView(entry: createShortEntry())
MonsterEntryView(entry: createLongEntry())
}
}
private static func createShortEntry() -> Entry {
.init(
date: Date(),
name: "1",
description: "1",
icon: UIImage(named: "Uhooi")!
)
}
private static func createLongEntry() -> Entry {
.init(
date: Date(),
name: "123456789012345678901234567890",
description: "12345678901234567890\n12345678901234567890\n12345678901234567890",
icon: UIImage(named: "Uhooi")!
)
}
}
おわりに
これでWidgetのさまざまなパターンのPreviewをまとめて確認できます!
もっといい方法や、他にも確認すべきパターンがあれば、コメントなどで教えていただけると嬉しいです
以上、 iOS Advent Calendar 2020 の10日目の記事でした。
明日は @MilanistaDev さんの記事です。