Reputation: 24942
I have a function with an if statement that in either case returns a Group()
, however, SwiftUI compiler doesn't recognize it as the same type. What's going on?
Getting error:
Function declares an opaque return type, but the return statements in its body do not have matching underlying types
private func cellWithContact(_ contact: CNContact) -> some View {
let displayName: String? = CNContactFormatter.string(from: contact, style: .fullName)
if let displayName = displayName {
return Group() {
Text(displayName)
}
}
return Group() {}
}
Upvotes: 1
Views: 181
Reputation: 49590
Opaque types still require there to be a concrete single type specified by a callee, but in your function you have two different return types:
return Group { Text(displayName) } // Group<Text> type
// and also
return Group { } // Group<EmptyView> type
So, you need to either
AnyView
:return AnyView(Group { Text(displayName) } // AnyView type
// ...
return AnyView(Group { }) // AnyView type
return Group { Text("") } // Group<Text> type, same as the other one
_ConditionalContent
) view, which ViewBuilder creates automatically when encountering an if/else
:@ViewBuilder // this is required
func cellWithContact(_ contact: CNContact) -> some View {
// ...
if someCondition { // _ConditionalContent<Group<Text>, Group<EmptyView>> type
Group { Text(...) }
} else {
Group { }
}
}
Upvotes: 3
Reputation: 54586
Other answers are perfectly fine. Just wanted to mention that if you're using SwiftUI 2 / iOS 14 you can use control flow statements (like if-let
) directly in a @ViewBuilder
block:
@ViewBuilder
private func cellWithContact(_ contact: CNContact) -> some View {
if let displayName = CNContactFormatter.string(from: contact, style: .fullName) {
Text(displayName)
}
}
And there’s no need to return EmptyView()
which makes the code much cleaner.
Upvotes: 1
Reputation: 258107
Here is possible solution. Tested with Xcode 12 / iOS 14.
@ViewBuilder
private func cellWithContact(_ contact: CNContact) -> some View {
let displayName: String? = CNContactFormatter.string(from: contact, style: .fullName)
if let displayName = displayName {
Text(displayName)
} else {
EmptyView() // or `Group {}`, but it is the same
}
}
Upvotes: 1