Open LucasVanDongen opened 2 months ago
Thanks for raising this issue!
Previews ran within a package rather than the main app have issues
Ah, this is something that I've not tried myself. I've only tested using previews in the main app target, which appeared to work just fine.
I'll try to reproduce this in the Dog Tracker sample app and get back to you.
So I had a bit of a look into this, but so far I haven't been able to reproduce the issue myself.
I came across this post - https://forums.swift.org/t/xcode-previews-swiftpm-resources-xcpreviewagent-crashed/51680 - is it the same issue?
I tried the sample project that the post author linked to using Xcode 15.2 but I can't reproduce the original issue on my side (am I doing something different?)
Would it be possible for you to provide me with a reproducer for this issue? You can use the xcstrings-tool-demo repo as a starting point if you would like.
Regardless of the bug with Xcode/SPM/Previews, I guess you might alternatively just be after a way to customise the Bundle yourself.. If this is common issue, I would like to address it with the generated code (i.e by using your extension for resolving Bundle
). I'd prefer this to providing ways to override the bundle used by the generator.
The reason for this is because the idea is that the generated code should already be sufficient.
That said, if you want to customise how the localizations are looked up, I am looking into adding a way to opt-out of generating the helper/accessor code so that you can just write it yourself instead - #104. Perhaps this might also work for you as you would just be able to substitute for your own bundle.
Anyway, let me know about the reproducer and if not, I can try to prioritise the helper opt-out change.
This zip file has a self-contained Module as a Swift Package, tested in Xcode 15.4
_LocalizationPreviews
WorkingPreviews
in the Previews
, this should work ("good")FailingPreviews
now, this should crashI think with a bit of perseverance, I can get a fork to work for my own purposes. But it would be great if this would be somehow supported automatically, so nobody has to deal with this anymore.
This is how SwiftGen solves it:
params:
bundle: Bundle.myPackage
When I add an image to the working view, it keeps working because of that:
VStack {
Button(action: test.test, label: {
Text(String.good)
})
Asset.amsterdamsepoortLogoColored.swiftUIImage
}
I noticed there's a flag XCSTRINGS_TOOL_ACCESS_LEVEL_PUBLIC
, perhaps we could also have something like XCSTRINGS_TOOL_BUNDLE_NAME
?
I think there is a significant subset of developers that cannot run Previews in their Xcode project anymore because of a combination of project size, Previews on big targets being brittle and Swift compile times. So that would either mean using something like Tuist to generate custom per-feature projects, or working inside of a Swift Package and use Previews from there.
I prefer to work in the Swift Module because it will keep everything associated with the Module inside of there, the Previews will be available to everybody. And I use Snapshots on Previews as a form of testing my UI layer, which gives me a huge kick in code coverage basically for free!
Thanks for the reproducer and the explanation! I agree that this is something we should certainly resolve to allow developers to use previews in separate modules. I don't think the Apple suggested workaround (of using an App Xcode project) is a very good one.
I was able to reproduce the issue, but only when the run destination was set to a physical device and not a simulator. Is that the case for you as well?
perhaps we could also have something like
XCSTRINGS_TOOL_BUNDLE_NAME
?
This would be a quick fix, but unfortunately it isn't possible to pass key: value
configs in via swiftSettings - only flags, so you couldn't get something like a custom bundle name through.
That said, it also goes a bit against the motivation behind the build tool plugin. By tightly wrapping everything up into a build tool plugin, I don't want users to have to worry about getting the right bundle because the generated code should use the right bundle automatically.
For us to use the right bundle automatically, it's going to mean that we need to generate some custom code that will do the correct bundle lookup for us. I'm more than happy to do that based on the example that you shared when you created the issue.. I'll have a look at how I can integrate it so that it's isolated to just previews.
I had a further look into this tonight, and if your issue is the same as my issue (that only crashes when the destination is set to a physical device and not a simulator, even if the preview renders inside Xcode) then it seems that it has been fixed in Xcode 16 (beta 4).
I'm happy to still try and patch it, but if you could confirm to me that this is the same issue that you are seeing then it would be very helpful. Thanks!
I’m on holiday, just my phone and spotty connections, my apology for not being super responsive.
Currently seeing it everywhere:
I’m not sure what you mean by device. If it’s the one that looks like a device then yes, but I don’t remember the other ones working, but that might just be because I never tried.
thanks again for putting effort into this 🙏
Set Up
I have a Local Swift Package I use for separating my features and have a more quick iteration over features using local Previews that load fast and reliable because I don't need to build the whole project, nor include heavy 3rd party dependencies for my UI target.
Problem
One big issue is that Previews ran within a package rather than the main app have issues accessing values from a bundle like icons, fonts and translations. I used SwiftGen for everything, that works with some hacking using a custom bundle
.myPackage
(see below), but it doesn't support xcassets yet. XCStrings Tool does, and works really well, but I cannot control the bundle.Attempted Solution
For SwiftGen I can, and with the help of a custom bundle
.myPackage
it works everywhere. I don't see a way to do this in XCStrings Tool. I cloned the repo and tried to hard code.myPackage
but I wasn't able to make it work inside my local package, perhaps because the binary version of the plug-in just works better in that scenario? So I'm not sure if that direction of solution would actually work for me.Bundle.swift and Crash Log
Bundle.swift:
The pruned error report: