0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?

【Swift】Widgetの作成方法

Posted at

Widgetの準備をする

Widgetを作成したいプロジェクトをXcodeから開く。

File → New → targetを選択
file.png

Widget Extensionを選択
addWidget.png

こんな感じで追加されていればOK!
checkAddWidget.png

主なファイルの役割は以下の通りです

Widget
Widgetの見た目などを設定する
WidgetBundle
異なる種類のWidgetを扱える
WidgetLiveActivity
Live Activityを使用する時に使うファイル

コードの編集

1種類しかWidgetを使わないのであれば、WidgetBundleは必要ないので、全てコメントアウトします。

Widget.swift

Widgetファイルを編集していく

まず扱うデータを定義する。

デフォルトの状態で

Widget.swift
struct SimpleEntry: TimelineEntry {
    let date: Date
    let emoji: String
}

となっている場所がある。
ここではWidgetで扱うデータの型を指定する。
ここで注意するのは、

let date: Date

は必ず必要だということ。
例えばStringの配列を扱いたいのであれば

Widget.swift
struct SimpleEntry: TimelineEntry {
    let date: Date
    let data: [String]
}

と記述する。

データを取得する

Widgetで扱うデータを取得するのは、一番上にあるProvider内で行います。
まず、データを取得する前に仮置きするデータをあらかじめ決めておきます。
*すぐに表示できるように、データはここ以外の場所に置かないようにします。(データベースは使わない)

Widget.swift
struct Provider: TimelineProvider {
    //仮置きするデータを定義する関数
    func placeholder(in context: Context) -> SimpleEntry {
        //以下のように書いて定義する
        SimpleEntry(date: Date(), data: ["データ取得中"])
    }
}

このように、必ずSimpleEntry(先ほど定義したデータ型)を返すようにする。

そして、ホーム画面に追加するWidgetを選ぶ画面で表示するデータもあらかじめ定義します。
*すぐに表示できるように、データはここ以外の場所に置かないようにします。(データベースは使わない)

Widget.swift
struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        ...
    }
    //仮置きするデータを定義する関数
    func func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { {
        //以下のように書いて定義する
        let entry = SimpleEntry(date: Date(), data: ["サンプルデータ"])
        complpetion(entry)
    }
}

completionの()の中に返したいデータを指定します。
ここでも必ずSimpleEntryを返す

最後に本当に表示したいデータを定義します。

Widget.swift
struct Provider: TimelineProvider {
    func placeholder(in context: Context) -> SimpleEntry {
        ...
    }
    func getSnapshot(in context: Context, completion: @escaping (SimpleEntry) -> ()) { {
        ...
    }
    //本当に表示したいデータを定義する
    func getTimeline(in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        //以下のように書いて定義する
        let entry = SimpleEntry(date: Date(), data: ["サンプルデータ"])
        completion(Timeline(entries: [entry], policy: .atEnd))
    }
}

ここで注意するのは、SimpleEntryの配列をentriesに指定することで、Timelineという型を返す。

また、UserDefaultsを使うときはちょっとした工夫が必要だが、以下に書いてある。

またアプリでの変更をWidgetに即時反映させたい時は、UserDefaults操作の直後に

WidgetCenter.shared.reloadAllTimelines()

を記述する。

見た目を作る

Widgetは必ず、SwiftUIというフレームワークを使用して見た目を作る。
WidgetEntryViewというところに書いていく。
以下に例を示しておく。

Widget.swift
struct WidgetEntryView : View {
    //扱いたいデータが詰まっている変数
    var entry: Provider.Entry
    
    //この中に見た目をかく
    var body: some View {
        //ForEachは、tableViewみたいな、同じ見た目を複数作成するときに使う
        //entry.dataのところは配列型、id: \.selfはとりあえずそのまま書いておけばOK
        //dataは、entry.dataで取り出したデータのうちの、一つの要素のこと
        ForEach(entry.data, id: \.self) { data in
            //縦に並べるものをこの中にかく。横に並べる時はHStack、重ねたい時はZStack。
            VStack {
                //Textは文字を表示する。()の中に表示したい文字列を指定する。
                //.を使って、見た目を整える。
                Text(data[0])
                    .frame(maxWidth: .infinity, alignment: .leading)
                Text(data[1])
                    .foregroundStyle(.secondary)
                    .font(.caption)
                    .frame(maxWidth: .infinity,alignment: .leading)
                    .padding(.bottom, 2)
            }
        }
    }
}

これでWidgetを最低限表示できるようになりました!

お疲れ様でした!

0
0
0

Register as a new user and use Qiita more conveniently

  1. You get articles that match your needs
  2. You can efficiently read back useful information
  3. You can use dark theme
What you can do with signing up
0
0

Delete article

Deleted articles cannot be recovered.

Draft of this article would be also deleted.

Are you sure you want to delete this article?