Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

SwiftUI: Function declares an opaque return type, but the return statements in its body do not have matching underlying types

Tags:

swift

swiftui

I was trying to write a static function like this:

enum NavigationViewKind {
    case test1(String)
    case test2
}

struct NavigationViewManager {
    static func make<V: View>(_ kind: NavigationViewKind, _ contentView: @escaping () -> V) -> some View {
        switch kind {
        case .test1(let text):
            return NavigationView {
                contentView()
                    .navigationBarTitle(text, displayMode: .inline)
            }
        case .test2:
            return NavigationView {
                contentView()
                    .navigationBarTitle("Initial", displayMode: .large)
            }
        }
    }
}

But I'm getting this error :

Function declares an opaque return type, but the return statements in its body do not have matching underlying types

Can you please help me understanding and solving this error?

Thank you

like image 912
Another Dude Avatar asked Oct 29 '20 08:10

Another Dude


People also ask

What is opaque type in Swift UI?

An opaque type refers to one specific type, although the caller of the function isn't able to see which type; a protocol type can refer to any type that conforms to the protocol.

How do I return a view in Swiftui?

on the -> View return type. From some research it looks like I could change this to some View and they wrap all my returns as AnyView but that feels like it's the wrong approach.

What is the some keyword in Swift?

The some keyword was introduced in Swift 5.1. It is used together with a protocol to create an opaque type that represents something that is conformed to a specific protocol. When used in the function's parameter position, it means that the function is accepting some concrete type that conforms to a specific protocol.


1 Answers

You need to use @ViewBuilder in this case (and remove returns, because return disables ViewBuilder)

struct NavigationViewManager {
    @ViewBuilder
    static func make<V: View>(_ kind: NavigationViewKind, _ contentView: @escaping () -> V) -> some View {
        switch kind {
        case .test1(let text):
            NavigationView {
                contentView()
                    .navigationBarTitle(text, displayMode: .inline)
            }
        case .test2:
            NavigationView {
                contentView()
                    .navigationBarTitle("Initial", displayMode: .large)
            }
        }
    }
}
like image 119
Asperi Avatar answered Sep 24 '22 02:09

Asperi