bitbank techblog

WidgetKitでウィジェットつくろ

これは ビットバンク株式会社 Advent Calendar 2020 の 15 日目の記事です。

パズルとドラゴンのゲームを続けてはや8年。(ランク1029)
最近はFortniteをやっています。(スキンはピーリー🍌)(シーズン5始まりましたね。)

どうもpeely_daisukeです。

開発環境

macOS BigSur Ver11.0.1
Xcode12.3-beta

まず弊社のウィジェット

1
この子ホーム画面に置けない、1時代前のやつなんですよね。

なので。。。

上司の許可も取らずに勝手に作ってみようと思い立ちました。

いいんですよ。
自分が楽しければ

Meet WidgetKit

「なんぞや」って方は、こちらを。(約20分)

WWDC2020 Meet WidgetKit

「いや、ええからはよ」って方は、こちらを。
Creating a Widget Extension

流れ

  • データの取得/整形 (bitbankアプリのものを流用)
  • 配置
  • データを表示

以上で、進めていきます。

データ取得/整形

すでに実装されているものを流用するため割愛。

割愛したけど、ほんのちょっとだけ。
APIを叩いて、表示に必要なものを生成しています。

今回は簡易実装のため1銘柄のみですが。。。🤫

Timelineに関係することを少しだけ。

Widgetの更新はTimeline更新で行われる。

複数のTimelineEntryを渡すことにより、一連の違う状態の静的なViewを生成でき、
指定された時間に表示してくれる。

あくまで、依頼であって必ず更新されるとは限らない。
富豪的な更新をするのではなく、必要なところだけをバックグラウンドなどで取得していきましょう。

struct OrewidgetProvider: IntentTimelineProvider {
    // データ取得できない時にデータ表示させたい時用。
    // (ここはMockじゃなくて最後に取得した物を入れれば良かった。)
    func placeholder(in context: Context) -> DataEntry {
        DataEntry(date: Date(), tickerData: mockTickerData, change: mockChange, configuration: ConfigurationIntent())
    }

    // プレビュー/ギャラリー用のためMockデータを差し込み。
    func getSnapshot(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (DataEntry) -> ()) {
        let entry = DataEntry(date: Date(), tickerData: mockTickerData, change: mockChange, configuration: configuration)
        completion(entry)
    }
    
    func getTimeline(for configuration: ConfigurationIntent, in context: Context, completion: @escaping (Timeline<Entry>) -> ()) {
        // entriesにどんどん追加していく形になる。
        var entries: [SimpleEntry] = []
        
        // 15分ごとにタイムラインの更新を要求させる。
        let ref = Calendar.current.date(byAdding: .minute, value: 15, to: Date()) ?? Date()
        
        // data, change ともに、既存のもののため省略。
        let entry = DataEntry(date: ref, tickerData: data, change: rate, configuration: configuration)
            
        entries.append(entry)
        
        let timeline = Timeline(entries: entries, policy: .after(ref))
        completion(timeline)
}

struct DataEntry: TimelineEntry {
    var date: Date
    let tickerData: TickerData
    let change: Double
    let configuration: ConfigurationIntent
}

配置

どこに何を置くか決めます。

2-4

イメージしているのは以下、

  • VStackが合計3つ。
    • 画像があり、銘柄名がある。
    • 売/買の価格が表示されている。
    • 変動率が表示されている。

何を表示させるか、イメージを持つことが大事です。

Figmaなどのデザインツールを使わずに、デザインをしてもらうこともいけそうだなと個人的には感じました。

var body: some View {
    // 1つ目
    Vstack {
        Image()
        Text()
        Text()
    }
    // 2つ目
    Vstack {
        Hstack {
            Image()
            Text()
        }
    }
    // 3つ目
    Vstack {
        Text()
    }

データを表示

データ、配置が決まればあとは上記のbody にデータをそれぞれ入れていきます。

🎉簡単ですね🎉
(※表示データは開発環境のものです。)

3-2

まとめ

今回Widgetをリプレイスしてみました。

Widgetの更新はTimelineで行われるので、実装の際は注意が必要そうです。

短い期間で実装できる良いフレームワークであると思います。

ただ、検索にあまり引っかからないのもまた事実です。

これからの、コミュニティの発展に期待です!!

--
以下、妄想です。

弊社の現行Widgetには、がございません!(チャート)
4-2

なので、もし実装することになったらここら辺も導入することも視野に入れないといけない気がしてきています。

また今回は、.supportedFamilies([.systemSmall])で一番小さい物でしか動作させていないので、medium/largeでも各々専用のものを作成するべきです。

ユーザがWidgetをカスタマイズできるため、取り組めれば取り組みたいです。以下、参照。
https://developer.apple.com/documentation/widgetkit/making-a-configurable-widget

現行のWidgetでは、タップするとアプリが開くだけだったので
シームレスに取引画面に遷移できるようにもしていきたいです。

という、クリスマスは一人虚しくFortniteをやっているであろう、男の妄想でした。

明日は、びっとぶりっと
さんの「Ethereumのトランザクションを解析してdefiトレードの損益計算する」です!

expand_less