しめ鯖日記

swift, iPhoneアプリ開発, ruby on rails等のTipsや入門記事書いてます

iOS16のロック画面のウィジェットを試してみる

iOS16でロック画面にウィジェットが出せるようになったので試してみました。

まずは通常のアプリ同様にプロジェクトを作成します。

次はプロジェクト設定のTARGETS下部にあるプラスボタンからターゲットを追加します。

追加するのはWidget Extensionです。

名前を付けて作成します。

途中でSchemeを追加するか聞かれるので追加します。
追加する事で下のようにウィジェットを選んで立ち上げできるようになります。

実行すると下のようにホーム画面にウィジェットが追加される事が分かります。

次はロック画面にもウィジェットを追加していきます。

サポートするためにWidgetConfigurationにsupportedFamiliesを追加する必要があります。

@main
struct MyAppWidget: Widget {
    let kind: String = "MyAppWidget"

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            MyAppWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
        .supportedFamilies([.accessoryRectangular])
    }
}

iOS15以下はaccessoryRectangularが使えないので下のように分岐を入れる必要があります。

@main
struct MyAppWidget: Widget {
    let kind: String = "MyAppWidget"

    var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
            MyAppWidgetEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
        .supportedFamilies(supportedFamilies())
    }
    
    func supportedFamilies() -> [WidgetFamily] {
        if #available(iOSApplicationExtension 16.0, *) {
            return [.accessoryRectangular]
        } else {
            return [.systemSmall]
        }
    }
}

iOSでサポートされている形式は下の3つです。

accessoryInline accessoryCircular accessoryRectangular
日付の横(時刻の右上に表示されるウィジェット) 時刻の下に表示される、円形 時刻の下に表示される、四角で円形2個分のサイズ

ウィジェットの実装は下の通りです。
実装はホーム画面のウィジェット同様です。

struct MyAppWidgetEntryView : View {
    var entry: Provider.Entry

    var body: some View {
        Text("ウィジェットテスト").frame(maxWidth: .infinity, maxHeight: .infinity).background(.black)
    }
}

widgetFamilyによって表示を変える場合は下のようにします。

struct MyAppWidgetEntryView : View {
    @Environment(\.widgetFamily) var family
    var entry: Provider.Entry

    var body: some View {
        switch family {
        case .accessoryInline: Text("accessoryInline").frame(maxWidth: .infinity, maxHeight: .infinity).background(.black)
        case .accessoryCircular: Text("accessoryCircular").frame(maxWidth: .infinity, maxHeight: .infinity).background(.black)
        case .accessoryRectangular: Text("accessoryRectangular").frame(maxWidth: .infinity, maxHeight: .infinity).background(.black)
        default: Text("")
        }
    }
}