Anyone successful with shared SwiftUI views?

I'm beginning to wonder just how viable SwiftUI is for apps. Keep running into serious issues.

For example, I have several existing UIKit apps. All have the same exact about screen. I created a storyboard with the UI along with a view controller .swift file that can be added to all my projects via simple file reference.

In trying to do the same with SwiftUI, I created an AboutView.swift file that lives outside the project's folder hierarchy:

Code Block
+ Common
+ Views
* AboutView.swift
+ MyApp
* MyApp.xcodeproj
+ Views
+ (folder/file reference here for Common items)
...

In my app project, I just dragged in the dependent AboutView.swift file.

Xcode (12.4) refuses to generate a preview though for AboutView. Giving me "Cannot preview in this file - active scheme does not build this file". That is false, when adding AboutView to the project, I included it in the app and UITest targets.

If I copy AboutView into the project (now just another local source file specific to that project), previews work again. I refuse to have twelve copies of these shared files; one per project!

I also tried folder references (e.g. dragging in that Common folder above). Same issue.

Tried a workspace that contained my app project and a simple project with my common views. Same issue.

Didn't even try local packages due to those failing miserably for me (separate thread on this forum with all those issues).

Side note: Building and running the app works great, it shows my about screen.

How is one supposed to be able to create a SwiftUI view and shared it across two or more projects? Why can't these be previewed? Each of my apps Assets.xcassets contains a Logo asset that is used in the about screen, so would be nice to see it in a preview and not have to rely on running the app in the simulator or on a device.

Finally, I'm thinking that Xcode can only generate previews of SwiftUI views in a project IFF their files are direct decendents on the project file's main folder on disk. Is that true? If so, why?

Accepted Reply

Solution found: At most one Xcode project can be open that contains your shared SwiftUI views. Read on for final details on this crazy journey

The plot thickens... Now the project where it started to magically work now fails again. I also found no differences in project settings between all my attempted projects.

Also, the original project the houses that shared SwiftUI view... it too now fails with cannot preview in this file... Zapping that project's derived data fixes the issue.

Re-opened separate project that had worked above. Still fails. Zapped its derived data. Preview still fails. Zapped shared project's derived data. Preview works!

Appears that derived data that is messing up everything. NOTE: For my shared views, I had "wrapped them" inside their own project. But this is most likely messing things up since I have a single SwiftUI file I want to share, but the build system cannot deal with that setup.

Then tried the following (also fails). Created a simple folder structure on my data drive (IIKit folder containing a Views subfolder containing IIAboutView.swift). Deleted all derived data. If I open one of my app project, preview works. Once I try to work on another project (even when closing the first), preview dies there. Re-opening the original project, preview dies there too.

My derived data is set to "Unique". Tried "Shared" same issues... but then...

Previews started to work again. Then it finally clicked. As long you only have one Xcode project open at any given time that uses the shared SwiftUI view source, all is well! I can easily now repeat the issue by opening a second Xcode project. Previews now fail with that error. You have to then close all Xcode projects and just open one.

I believe during this morning's vast majority of attempts, I had my IIKit project open.

Not a huge deal to only have a single Xcode project open at a time. At least a workaround exists. Will though still file a bug.


Replies

Thankfully, shortly after writing the above, I found a working solution.

Inside your app project (that wants to use shared SwiftUI views) you cannot use folder references or create "new group without folder" that will contain the shared items.

Instead, I created a regular group inside my app project (just for organization). Then, dragged in the shared views/items.

File system:

Code Block
+ IIKit
+ Views
* IIAboutView.swift
+ MyApp
* MyApp.xcodeproj
+ MyApp
+ IIKit
+ Views (note that this folder is empty; doesn't contain a copy of the IIKit items)


Xcode main window:

Code Block
+ MyApp
+ IIKit
+ Views
* IIAboutView.swift (location of this is the "real" IIKit shared folder items)
+ MyApp
+ Views
...


Completely non-intuative. Going to file a bug since in all my trials, the shared code resides in the same location on disk. Xcode should have worked with either folder references are when placing the shared items inside folders created with "new group without folder".
Nope; the only reason the above worked was because I was using a workspace. But dragging around the shared files ultimately messed that all up.

When I recreated an App project, no matter how I drag in the shared source, it cannot be previewed. Folder reference, In a group with/without a folder.

An alias also fails since Xcode just dumps the alias file's contents itself into the Xcode editor.

Finally, for good measure, tried a swift package as follows, but that also fails. I can live with some of the SwiftUI issues I've been experiencing; most have decent workarounds. But this issue is a deal killer if I cannot share code across my projects. At least with the shared Storyboard file in my UIKit projects, each project would display that storyboard a-ok. So why should a SwiftUI preview be any different?

Swift package steps...
  1. Created a brand new iOS single view app project.

  2. Added a new SwiftUI file (MyView) that simply uses the defaults from the template (i.e. body has a single Text element). Preview at this point works a-ok.

  3. Created a new Swift package and added it to the exiting project.

  4. Dragged MyView.swift into the package Sources and it will now no longer preview (Cannot preview in this file - active scheme does not build this file).

What the... when searching forums earlier, had a typo, but finally found some threads regarding the preview error.

For example: active scheme does not build this file

In that thread, one solution was to ensure that the file's location (in the Xcode Identity and Type inspector) is set to Relative to Project instead of Relative to Group.

So... I re-created groups without folders in my Xcode project. Re-dragged in the shared source. But the preview then worked! Location is set to Relative to Group which makes sense. So why oh why did the first several times of doing this all fail?

I had even restarted Xcoded, deleted all derived data earlier this morning during the above trials. Makes not sense that this would just magically start to work.

ARG... Created a brand new project to see if now repeatedly will work. Nope! In the project that just started to work, I had previouslly tried the Swift package (but have since deleted that package). So my new theory is that this Xcode project got some configuration added whereas the new project doesn't. Time to compare the project files for clues.
Solution found: At most one Xcode project can be open that contains your shared SwiftUI views. Read on for final details on this crazy journey

The plot thickens... Now the project where it started to magically work now fails again. I also found no differences in project settings between all my attempted projects.

Also, the original project the houses that shared SwiftUI view... it too now fails with cannot preview in this file... Zapping that project's derived data fixes the issue.

Re-opened separate project that had worked above. Still fails. Zapped its derived data. Preview still fails. Zapped shared project's derived data. Preview works!

Appears that derived data that is messing up everything. NOTE: For my shared views, I had "wrapped them" inside their own project. But this is most likely messing things up since I have a single SwiftUI file I want to share, but the build system cannot deal with that setup.

Then tried the following (also fails). Created a simple folder structure on my data drive (IIKit folder containing a Views subfolder containing IIAboutView.swift). Deleted all derived data. If I open one of my app project, preview works. Once I try to work on another project (even when closing the first), preview dies there. Re-opening the original project, preview dies there too.

My derived data is set to "Unique". Tried "Shared" same issues... but then...

Previews started to work again. Then it finally clicked. As long you only have one Xcode project open at any given time that uses the shared SwiftUI view source, all is well! I can easily now repeat the issue by opening a second Xcode project. Previews now fail with that error. You have to then close all Xcode projects and just open one.

I believe during this morning's vast majority of attempts, I had my IIKit project open.

Not a huge deal to only have a single Xcode project open at a time. At least a workaround exists. Will though still file a bug.


I think this might be related to Xcode's installation path, and how iCloud interacts with folders like Downloads. None of the suggestions I've seen around resolved this but it's now consistently working for me after I moved Xcode into Applications. It was in Downloads and I never realized since I keep it pinned.