mackoj
(Jeffrey Macko)
1
Hi,
Why the first part work and not the second ?
import SwiftUI
// Why does this works
enum Blueprint {
case boeing747
case concorde
}
protocol Plane { }
struct Boeing747: Plane { }
struct Concorde: Plane { }
func factory(_ blueprint : Blueprint) -> some Plane {
return Boeing747()
}
// And this does not work ?
enum Screen {
case homepage
case setting
case loggin
}
struct HomePage: View { var body: some View { Text("Homepage") } }
struct Setting: View { var body: some View { Text("Setting") } }
struct Loggin: View { var body: some View { Text("Loggin") } }
func screenBuilder(_ screen : Screen) -> some View {
switch screen {
case .homepage:
return HomePage()
default: break
}
return Text("Not Implemented")
}
I don't understand why I have this error.
error: SwiftUIRouter.playground:37:6: error: function declares an opaque return type, but the return statements in its body do not have matching underlying types
func screenBuilder(_ screen : Screen) -> some View {
^
SwiftUIRouter.playground:40:12: note: return statement has underlying type 'HomePage'
return HomePage()
^
SwiftUIRouter.playground:43:10: note: return statement has underlying type 'Text'
return Text("Not Implemented")
Alejandro
(Alejandro Alonso)
2
You’re returning two different types of Views, only 1 type of View can be returned.
mackoj
(Jeffrey Macko)
3
Ok but opaque result type should allow me to return objects of different type that conform to the same protocol ? No ?
Because this won't work either.
func screenBuilder<T : View>(_ screen : Screen) -> T {
switch screen {
case .homepage:
return HomePage()
default: break
}
return Text("Not Implemented")
}
Avi
4
No.
Opaque result types only hide the type from the caller. The callee still has to honor the contract, which is that a function returning an opaque type always returns the same concrete type.
3 Likes
mackoj
(Jeffrey Macko)
5
Okay I will find another way thanks
young
(rtSwift)
6
Use the @ViewBuilder If/Else:
@ViewBuilder
func screenBuilder(_ screen : Screen) -> some View {
if screen == .homepage: {
HomePage()
} else {
Text("Not Implemented")
}
}
You can keep adding else if to handle any number of "cases".
Unfortunately the Swift compiler in Xcode 11.3.1 is a little buggy now and the above code may not conpile. See I'm stumped with this @ViewBuilder on var body: some View compile error: Cannot convert return expression of type '_ConditionalContent<Text, Text>' to return type 'some View'
You can get around the bug by first create an variable and use that in the If/Else:
let homePage = HomePage() // <== work around the bug
let text = Text("Not Implemented")
@ViewBuilder
func screenBuilder(_ screen : Screen) -> some View {
if screen == .homepage: {
homePage // <== use this instead
} else {
text
}
}
1 Like
mackoj
(Jeffrey Macko)
7
I have tried what you proposed before it compiled but don't work properly.
It was like the return did not work properly.
I will try it again, thanks.