Type '() -> N' cannot conform to 'View'

There are questions with the same title on StackOverflow but they have nothing to do with what I am asking.

I have this highlight style for a button.

struct HighlightableButtonStyle<N, H>: ButtonStyle where N: View, H: View {
  
  private let alignment: Alignment
  private let normal: () -> N
  private let highlighted: () -> H
  
  init(alignment: Alignment = .center, 
       @ViewBuilder normal: @escaping () -> N,
       @ViewBuilder highlighted: @escaping () -> H) {
    self.alignment = alignment
    self.normal = normal
    self.highlighted = highlighted
  }
  
  func makeBody(configuration: Configuration) -> some View {
    configuration.label
      .frame(maxWidth: .infinity, maxHeight: .infinity)
      .contentShape(Rectangle())
      .background(alignment: alignment, content: {
        configuration.isPressed ? Color.red : Color.blue //1
      })
  }
}

My problem is with the line marked with //1.

If the line is at is is, it compiles fine, but I would like to pass colors to the style, so I change that line to

configuration.isPressed ? highlighted : normal

and I get this error

Result values in '? :' expression have mismatching types '() -> H' and '() -> N'
Insert ' as! () -> N'
Type '() -> N' cannot conform to 'View'

The most intriguing is the last line. How can N not conform to view?

What am I missing?

>Solution :

highlighted and normal are functions. You should call them (by adding () at the end) to make them produce a View.

if configuration.isPressed {
    highlighted()
} else {
    normal()
}

Note that you cannot use the ternary operator here because highlighted and normal return different types – H and N respectively.

Leave a Reply