Home > Blockchain >  Swift and Binding shorthand
Swift and Binding shorthand

Time:09-27

let _ = Binding(get: { x }, set: { x = $0 })

Seems quite long when you have more complex getters and setters. And I was wondering if there could be easier way. I do know @focusState, but let's forget it for now.

Let's try something..

public protocol FocusEnum: Equatable {

    //func binding(_ equals: Self) -> Binding<Bool>
    
}

extension Optional where Wrapped: FocusEnum {
    
    func binding(_ equals: Self) -> Binding<Bool> {
        Binding(get: { self == equals }, set: { self = $0 ? equals: nil })
    }
}

This won't work, self is immutable. If I change it to mutable func- no go, as then closure would be capturing inout parameter...

This would be just very handy..

enum focusEnum: FocusEnum {
        case field1
        case field2
}

...


@State var focused: focusEnum? = nil

and to get binding.. let _ = focused.binding(.field1)

Any ideas?

CodePudding user response:

I couldn't make it work. Too bad, it would had been nice to be able to make automatic by adding a protocol conformance.

I went around it and added this to View to get the same result..

func focusField(equals: FieldId) -> Binding<Bool> {
    Binding(get: { focused == equals ? true : false }, set: { focused = $0 ? equals : nil })
}

I have a BoolFocusible protocol adding isFocused(_ binding: Binding<Bool>) -> Self for my Views coming from UIViewRepresantable that require some extra attention to focus handling, mostly we talk about UITextFields here.

Then I have Cell View, that formats with Title and content to List, conforming to BoolFocusible, and if it's child is also BoolFocusible, it forwards automatically by casting Content as BoolFocusible and giving same binding to child View.

Though, if one has something to add to my attempt to make it easier like I first asked.. I'd love to hear about it- code is hard to read and compiler needs some time, almost too much- So anything goes ;)

CodePudding user response:

I made this..

protocol FocusingView {
    
    associatedtype FieldId: Equatable
    
    var focused: FieldId? { get nonmutating set }
    func focusField(equals: FieldId) -> Binding<Bool>
}

extension FocusingView {
    
    func focusField(equals: FieldId) -> Binding<Bool> {
        Binding(get: { focused == equals ? true : false }, set: { focused = $0 ? equals : nil })
    }

}

struct MyView: View, FocusingView {

    enum FieldId: Hashable {
        case field1
        case field2
        case field3
        case field4
    }
    
    @State var focused: FieldId? = nil
 ...
}

allows me to use focusField(equals: .field1) to get binding I wanted. This is one way to do it..

  • Related