Hudi Ilfeld
Hudi Ilfeld

Reputation: 2045

Force view that conforms to protocol to have a property wrapper in SwiftUI

I want to enforce certain Views to contain a @Binding property thus I created a protocol for this.

Like the following:

protocol DismissableView: View {
   var isPresented: Binding<Bool> { get set }
}

And when I want my View to conform to it, Like this:

struct MyView: DismissableView {
   @Binding var isPresented: Bool 
}

I get the following:

Type 'MyView' does not conform to protocol 'DismissableView'

which I reckon is got to do with the fact that @Binding is not the same as Binding<Bool>

As you all are obviously aware of the fact that I cannot decalare a propertyWrapper in a protocol thus I am unable to simply declare in the protocol a @Binding directly, I am pretty stuck here.

What am I to do?

Upvotes: 1

Views: 790

Answers (1)

Asperi
Asperi

Reputation: 258057

Here are possible variants:

a) use stored property the same as in protocol (drawback: access via wrappedValue)

struct MyView: DismissableView {

    var isPresented: Binding<Bool>

    var body: some View {
        Text(isPresented.wrappedValue ? "Presented" : "Not")
    }
}
  1. use internal variable with wrapper to conform to protocol (drawback: needed wrapper in each confirmed view)
struct MyView: DismissableView {

    var isPresented: Binding<Bool> {
        get { _presented }
        set { _presented = newValue }
    }

    @Binding var presented: Bool

// optional init if needed to have MyView(isPresented: Binding<Bool>) interface

//    init(isPresented: Binding<Bool>) {
//       self._presented = isPresented
//    }

    var body: some View {
        Text(presented ? "Presented" : "Not")
    }
}

External usage in both cases is same.

Note: the @Binding var isPresented: Bool property wrapper being unwrapped creates two properties (see below) that is why you cannot confirm it directly

var isPresented: Bool
var _isPresented: Binding<Bool>

Upvotes: 2

Related Questions