2

Since Swift has no real first-class namespace support, enums are often used as a replacement. When doing so, SwiftUI previews don't build anymore:

import SwiftUI

enum Namespace { }

extension Namespace {
    struct ContentView: View {
        var body: some View {
            VStack {
                Text("ContentView")
                    .padding()
                InnerView()
                    .padding()
            }
        }
    }

    struct InnerView: View {
        var body: some View {
            Text("InnerView")
        }
    }
}

#if DEBUG
struct NamespaceContentViewPreviews: PreviewProvider {
    static var previews: some View {
        Namespace.ContentView()
    }
}
#endif

This produces a "Failed to build ContentView.swift" error with the diagnostic

Compiling failed: cannot find 'InnerView' in scope
.../NamespaceTest/ContentView.swift:19:17: error: cannot find 'InnerView' in scope

Note that the code compiles and runs just fine when building the app, it's just the previews I'm having problems with.

Adding typealias Innerview = Namespace.Innerview after the #if DEBUG helps, but for larger views with many subview this gets really tedious really fast.

Adding the PreviewProvider to the namespace does not help, unfortunately - simply moving it inside an extension Namespace{} disables previews entirely, and forwarding to a namespaced struct also doesn't help, either:

extension Namespace {
    struct ContentViewPreviews: PreviewProvider {
        static var previews: some View {
            ContentView()
        }
    }
}

struct NamespaceContentViewPreviews: PreviewProvider {
    static var previews: some View {
        Namespace.ContentViewPreviews.previews
    }
}

leads to two "cannot find X in scope" errors :-(

The issue is present in Xcode 13.4.1 as well as Xcode 14 beta 6.

Is there another/easier way to get SwiftUI previews to work inside enums/namespaces?

1 Answer 1

0

You have two issues with your code:

First, Namespace is a SwiftUI keyword to name related MatchedGeometry. You were having a conflict in namespaces, ironically. I changed your Namespace to MyNamespace, and the errors went away. But is still won't run.

Second, once you go with a namespace, you have to use the namespace. So, you have to refer to InnerView() in Namespace.ContentView as Namespace.InnerView(). It will then build and run.

So, your code would be:

enum MyNamespace { } // Here

extension MyNamespace { // Here
    struct ContentView: View {
        var body: some View {
            VStack {
                Text("ContentView")
                    .padding()
                MyNamespace.InnerView() // Here
                    .padding()
            }
        }
    }

    struct InnerView: View {
        var body: some View {
            Text("InnerView")
        }
    }
}

struct Namespace_Previews: PreviewProvider {
    static var previews: some View {
        MyNamespace.ContentView()
    }
}
Sign up to request clarification or add additional context in comments.

4 Comments

I think you're referring to the @Namespace property wrapper - this does not collide in any way with the (example) Namespace enum I'm using. My test app builds and runs just fine, it's only the previews that generate errors. Regarding your second point: Swift's type resolution works from inner types outwards and finds the first match, so referring to just InnerView from within Namespace works as expected. See e.g. docs.swift.org/swift-book/LanguageGuide/NestedTypes.html for an "official" example.
Well, have you actually tried the code? Further, you are dealing with structs in an enum, not enum cases.
Yes I did, and it did not really address the issue I'm having. This question is not about the View itself - like I said, it compiles and runs just fine. The question is about why this valid piece of code does not work in the context of previews.
My code works perfectly in previews. Added preview provider code.

Your Answer

By clicking “Post Your Answer”, you agree to our terms of service and acknowledge you have read our privacy policy.

Start asking to get answers

Find the answer to your question by asking.

Ask question

Explore related questions

See similar questions with these tags.