'SwiftUI function that returns either Text or Button?

I have a simple function to return either Text or Button, but I get the following error:

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

Here's my function:

private func cellContent(for cell: Cell) -> some View {
  if (cell.editable) {
    return Button(action: { print("hi") }) { Text(cell.content) } 
  }
  return Text(cell.content)
}

How can I fix this or do it different way?



Solution 1:[1]

Here is correct variant.

Note: ViewBuilder is disabled when you use explicitly return, so you have to remove return(s) when use it otherwise you'll get compiler errors again.

Tested with Xcode 12 / iOS 14

@ViewBuilder
private func cellContent(for cell: Cell) -> some View {
  if (cell.editable) {
     Button(action: { print("hi") }) { Text(cell.content) }
  }
  Text(cell.content)
}

Solution 2:[2]

this is the exact `where` of where to use @ViewBuilder. just add an @ViewBuilder to the beginning of your function:

@ViewBuilder
private func cellContent(for cell: Cell) -> some View {
  if (cell.editable) {
      Button(action: { print("hi") }) { Text(cell.content) } 
  }
      Text(cell.content)
}

What is @ViewBuilder? you can get detailed info on the internet, but a good, yet short explanation would be that it does exactly what it is doing in this example! it converts closures to Views, while removing compile errors.

As said in the comments, you should remove returns too, @ViewBuilder will turn the whole function's closure to a new single view, and will automatically return that new view, so explicit return's are not needed.

Sources

This article follows the attribution requirements of Stack Overflow and is licensed under CC BY-SA 3.0.

Source: Stack Overflow

Solution Source
Solution 1 Asperi
Solution 2