I'm trying to write an extension which adds a caption (I called it statusBar
) right below it, no matter what type the caption is (e.g. Text, Image, Link...). So I tried the code below. But Xcode said an error at the line before .statusBar
that Type '()' cannot conform to 'View'
. You can find I added a comment in the code below.
I know there must be something wrong within my .statusBar
, because the error disappeared when I replaced my if-let-else block with a single view (e.g. Text("Hello, world!")). But I still want to display different contents based on that if-let statement. So how can I do with my code to solve this?
// .statusBar extension
struct StatusBarView: ViewModifier {
let statusBar: AnyView
init<V: View>(statusBar: () -> V) {
self.statusBar = AnyView(statusBar())
}
func body(content: Content) -> some View {
VStack(spacing: 0) {
content
statusBar
}
}
}
extension View {
func statusBar<V: View>(statusBar: () -> V) -> some View {
self.modifier(StatusBarView(statusBar: statusBar))
}
}
// Inside main app view
Image(systemName: "link")
.font(.system(size: 48)) // Xcode error: Type '()' cannot conform to 'View'
.statusBar {
//
// If I change below if-let-else to a single view
// (e.g. Text("Hello, world!"))
// Then it works.
//
if let url = mediaManager.url {
Text(url.path)
} else {
Text("No media loaded.")
}
}
CodePudding user response:
Make it closure argument a view builder, like
extension View {
func statusBar<V: View>(@ViewBuilder statusBar: () -> V) -> some View {
self.modifier(StatusBarView(statusBar: statusBar))
}
}
the same can be done in init of modifier, but not required specifically for this case of usage.
Tested with Xcode 13.4 / iOS 15.5
CodePudding user response:
Wrap if-else into Group. Example:
Image(systemName: "link")
.font(.system(size: 48))
.statusBar {
Group {
if let url = mediaManager.url {
Text(url.path)
} else {
Text("No media loaded.")
}
}
}
CodePudding user response:
You can also do like this
Image(systemName: "link")
.font(.system(size: 48))
.statusBar {
ZStack {
if let url = mediaManager.url {
Text(url.path)
} else {
Text("No media loaded.")
}
}
}