iOS 14 Widgets + SwiftUI + Firebase?

后端 未结 3 1286
旧巷少年郎
旧巷少年郎 2020-12-31 21:17

I\'m still pretty new to SwiftUI and Firebase. Recently, as a hobby, I have been developing an app for my school. After the launch of Xcode 12, I decided to experiment with

相关标签:
3条回答
  • 2020-12-31 21:47

    Your main app needs to pass data to your extension, this can be achieved by allowing your app to use "App Groups" capability. What App Groups does is, it creates a container where your app can save data for you to share with your app extensions. So follow these steps to enable "App Groups".

    1. Select your main App Target>Signing & Capabilities then tap + Capability and select "App Groups"

    2. Tap on "+" to add a new container, and add a name to it after group. example : "group.com.widgetTest.widgetContainer"

    Once you have created the "App Group" on your main app, you should take the same steps but on your "Widget Extension" target. This time, instead of creating a container, you should be able to select the container you already have from the main app. You can find a good video on YouTube explaining this process really well on here How to Share UserDefaults with app extensions

    The next step I recommend is to create a Swift Package or a Framework, and add a new Model Object, this model object is the one you will be passing from your main app, to your widget extension. I chose a Swift Package.

    To do this follow these steps:

    1. File>New>Swift Package

    A good video from the WWDC19 about this can be seen here

    2. In your Swift Package, inside the "Sources" folder, Create a Custom Model which you will use in both your Main App, and Widget Extension

    Make your object conform to "Codable" and that it is Public.

    Important Make sure you import "Foundation" so that when you are decoding/encoding your object, it will do it properly.

    3. Add your Package to your Main App and Widget Extension

    • Select your App's Target>General> Scroll to "Frameworks, Libraries, and Embedded Content"
    • Tap "+" and search for your Package

    • Do the same steps on your Widget's Extension

    Now, all you need to do is "import" your module in the file that you will be creating your custom object in both your Main App, and on your WidgetExtension, then initialize your shared object on your main app and save it to UserDefaults by first encoding the object to JSON and then saving it to UserDefaults(suiteName: group.com.widgetTest.widgetContainer)

    let mySharedObject = MySharedObject(name: "My Name", lastName: "My Last Name")
                       
     do {
         let data = try JSONEncoder().encode(mySharedObject)
    
          /// Make sure to use your "App Group" container suite name when saving and retrieving the object from UserDefaults
          let container = UserDefaults(suiteName:"group.com.widgetTest.widgetContainer")
              container?.setValue(data, forKey: "sharedObject")
                            
          /// Used to let the widget extension to reload the timeline
          WidgetCenter.shared.reloadAllTimelines()
    
          } catch {
            print("Unable to encode WidgetDay: \(error.localizedDescription)")
       }
    
    

    Then in your widget extension, you want to retrieve your object from UserDefaults, decode it and you should be good to go.

    Short Answer

    Download your Firebase data, create a new object from that data, encode it to JSON, save it on your container by using UserDefaults, retrieve the object in your extension from the container, decode it and use it for your widget entry. Of course, all of this is assuming you follow the steps above.

    0 讨论(0)
  • 2020-12-31 21:54

    You can add the appDelegate to your @main SwiftUI view

    First create your appdelegate on your widget extension

    import Firebase
    
    class AppDelegate: NSObject, UIApplicationDelegate {
        func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey : Any]? = nil) -> Bool {
            FirebaseApp.configure()
            return true
        }
    }
    

    look at @main, inside your widget extension,

    @main
    struct TestWidget: Widget {
        @UIApplicationDelegateAdaptor(AppDelegate.self) var appDelegate
    
        private let kind: String = "ExampleWidget"
    
        public var body: some WidgetConfiguration {
           ...
        }
    }
    

    @main is new swift 5.3 feature that allows value type entry point, so this is will be your main entry point for your widget extension

    just add @UIApplciationDelegateAdaptor, inside your @main

    0 讨论(0)
  • 2020-12-31 22:09

    I can confirm after testing that the following method works to use Firebase in the Widget Target without incorporating an app group, user defaults or anything else.

    @main
    struct FirebaseStartupSequence: Widget {
      init() {
        FirebaseApp.configure()
      }
    
      let kind: String = "FirebaseStartupSequence"
    
      var body: some WidgetConfiguration {
        IntentConfiguration(kind: kind, intent: ConfigurationIntent.self, provider: Provider()) { entry in
          FirebaseStartupSequenceEntryView(entry: entry)
        }
        .configurationDisplayName("My Widget")
        .description("This is an example widget.")
      }
    }
    

    Simply use the init method in your widget to access a firebase instance.

    This was the easiest solution for me as of today.

    Taken from: https://github.com/firebase/firebase-ios-sdk/issues/6683

    Additional Edit: Do you need to share authentication? No problem. Firebase has that covered here: https://firebase.google.com/docs/auth/ios/single-sign-on?authuser=1

    0 讨论(0)
提交回复
热议问题