I guess this is in parts a multiplatform / SwiftData / WidgetKit and SwiftUI question.
my usual problem is I start an app and then quickly find myself wanting to add widgets / controls / AppIntents and expand across multiple targets.
for example I start with an iOS only target and expand to watchOS, iPadOS and visionOS. But since this targets and the apps I want to build are very distinct, I don’t find myself using the multiplatform target but instead a target per platform. This (at least from my understanding) then also comes with the benefit that I can add a WidgetKit extension and all targets use it.
now this is the base idea, but here come the many questions I have had issues finding a clear answer and guidance on over the last years.
-
When sharing SwiftUI views and business logic for DRY, whats the actual best way to do that? A „core“ swift package, or a library? what are the implications of choosing one over the other?
-
I understand that widgets are separately scoped and sandboxed from my main app, but since I use SwiftData in the main app I‘ll have to use app groups so that both can have the same data store. Now; using query in widgets is no problem and is intuitive enough, but the ModelContext has to come from somewhere and be initialized somewhere Where? + additionally, talking about appintents for example when having a control or interactive widget, they also need to share the same context to have an immediate response and update all accordingly (so app, widgets and intents all need to have the same) but how do I actually do that when everything is sandboxed? I recently discovered the @Dependecy macro in I think it was an app intents talk, but it’s usage was skipped over and I couldn’t find documentation explaining what I need to do here to get this actually working.
i think the two above are my main questions and I hope I could give enough context to see where I fall short of understanding the architects involved.
so for big multiplatform apps where I want to adopt as many system features as possible what’s the best „separation“ or project structure here?
see, for example the default Apple Notes app would really interest me how they handle it, or Journal for that matter, since it targets so many platforms and has native features, how is the project structured at the top level? (Obv just an example of what scope I am looking for here)
sample code often falls short of what I need, or maybe then again I haven’t found the right one yet.
thanks for reading to this point and I am grateful every input, perspective and suggestion I can get here, since it will apply to all my projects
It’s hard to give definitive advice here because there are many different ways to do these things. But lemme take a stab at your two main questions:
When sharing SwiftUI views and business logic for DRY, whats the actual best way to do that? A „core“ swift package, or a library?
One of those, yes.
what are the implications of choosing one over the other?
If your library is only ever going to be used by an Xcode project then I think a framework target makes more sense. Swift packages do have significant advantages, but framework targets are directly implemented by Xcode and thus tend to work better when you’re building an app for Apple platforms.
I’ll have to use app groups so that both can have the same data store
Right. Technically what you use is an app group container. You sign your app to claim access to an app group, and the system then creates a on-disk container for that app group. You find the location of that container using the containerURL(forSecurityApplicationGroupIdentifier:) method.
At that point you have to point your store at a location in that container. I’m not really a SwiftData expert, but Preserving your app’s model data across launches says that you can use a ModelConfiguration for that.
If you have more specific questions about that, I recommend that you start a new thread in App & System Services > SwiftData, where the SwiftData experts hang out.
Share and Enjoy
—
Quinn “The Eskimo!” @ Developer Technical Support @ Apple
let myEmail = "eskimo" + "1" + "@" + "apple.com"