LoginSignup
2
1

More than 1 year has passed since last update.

WidgetKitで初心者の躓きどころ

Last updated at Posted at 2022-03-26

WidgetKitで初心者の躓きどころ

WidgetKitをみたら、いくつか躓きどころが合ったのでまとめてみました。

特にWidgetはメインのTargeと別なので
Targetが違うと色々参照できるようにする必要があります。

1. メインのターゲットを参照できない

参照したいファイルのTargetMembershipにチェックを入れればOK
※一つのファイルにいろんな依存物があると、それら全てをtチェックしないといけないので、各オブジェクト毎にファイルを分けるべし。

2. メインのTargetとは別でWidgetのTargetを作成するのでLibraryが参照できない。

Testなどと同様LibraryのTargetも追加する必要がある。

Cocoa Podsの場合

podファイルのWidgetのTarget内にinherit! :search_pathsを指定OK

  target 'SampleWidgetExtension' do
    inherit! :search_paths
  end

SwiftPMの場合

プロジェクトのWidgetのTargetのBuild Phasesで必要なLibraryを連携したらOK

3. DB内のデータが参照できない。

CoreDataやRealmを使っている場合
メインアプリのデータを参照するにはAppGroupで同じDBファイルを参照できるようにする必要がある。

AppGroupの設定

アプリの Target を選択し、Signing & Capabilities タブで、App Groups を追加します。
App Groupsの項目が無い場合は左上の+ボタンでダイアログの中からApp Groupsを選択。
新しいGroupを作成して下の更新ボタンをクリック。

※注意
Build Configurationが複数ある場合はそれぞれ必要なBuild ConfigurationでAppGroupの設定が必要

CoreDataの場合

NSPersistentStoreDescriptionのurlにAppGroup名を使って初期化します。


        let container = NSPersistentContainer(name: TodoListStore.containerName)
        container.persistentStoreDescriptions = [NSPersistentStoreDescription(url: FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.SampleWidget")!.appendingPathComponent("Sample.sqlite"))]
        container.loadPersistentStores(completionHandler: { (description, error) in
            if let error = error as NSError? {
                print("Unresolved error \(error), \(error.userInfo)")
            }
        })
        print(container.persistentStoreDescriptions.first?.url ?? "nil.splite")
        return container

Realmの場合

Realmインスタンスを作成する時に同じDBを参照するためにConfigurationのfileURLにAppGroupのURLを設定します。

        let realm = try! Realm()

このようにインスタンスを作っている箇所を下記に変更

        var config = Realm.Configuration()
        let url = FileManager.default.containerURL(forSecurityApplicationGroupIdentifier: "group.com.SampleWidget")!
        config.fileURL = url.appendingPathComponent("db.realm")
        let realm = try! Realm(configuration: config)

URLから取得して画像を表示する場合は非同期では動かない。

Widgetに置いてURL画像の表示をする場合非同期処理は使えない。
Widgetでは同期的に取得するべし。

  • 非同期処理の場合

            DispatchQueue.global().async {
                let data = try? Data(contentsOf: imageURL)
                DispatchQueue.main.async {
                    self.downloadData = data
                }
            }
  • 同期処理の場合
            let data = try? Data(contentsOf: imageURL)
            self.downloadData = data

最後に

WidgetはSwiftUIでの実装が必要なので、SwiftUIの勉強も兼ねてチャレンジしてみました。
まだ触り始めたばかりなので、また躓き所が出てきたら追記します。

参考

2
1
1

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
2
1