Lupurus
Lupurus

Reputation: 4189

Custom event modifier in SwiftUI

I created a custom button, that shows a popover. Here is my code:

PopupPicker

struct PopupPicker: View {

    @State var selectedRow: UUID?
    @State private var showPopover = false
    let elements: [PopupElement]

    var body: some View {
        Button((selectedRow != nil) ? (elements.first { $0.id == selectedRow! }!.text) : elements[0].text) {
            self.showPopover = true
        }
        .popover(isPresented: self.$showPopover) {
            PopupSelectionView(elements: self.elements, selectedRow: self.$selectedRow)
        }
    }
}

PopupSelectionView

struct PopupSelectionView: View {

    var elements: [PopupElement]
    @Binding var selectedRow: UUID?

    var body: some View {
        List {
            ForEach(self.elements) { element in
                PopupText(element: element, selectedRow: self.$selectedRow)
            }
        }
    }

}

PopupText

struct PopupText: View {

    var element: PopupElement
    @Binding var selectedRow: UUID?

    var body: some View {
        Button(element.text) {
            self.presentation.wrappedValue.dismiss()
            self.selectedRow = self.element.id
        }
    }
}

That works fine, but can I create a custom event modifier, so that I can write:

PopupPicker(...)
    .onSelection { popupElement in
        ...
    }

Upvotes: 2

Views: 1642

Answers (1)

Chiel
Chiel

Reputation: 1442

I can't give you a full solution as I don't have all of your code and thus your methods to get the selected item anyhow, however I do know where to start.

As it turns out, declaring a function with the following syntax:

func `onSelection`'(arg:type) {
...
}

Creates the functionality of a .onSelection like so:

struct PopupPicker: View {
    @Binding var selectedRow: PopupElement?
    var body: some View {
        ...
    }

func `onSelection`(task: (_ selectedRow: PopupElement) -> Void) -> some View {
        print("on")
        if self.selectedRow != nil {
            task(selectedRow.self as! PopupElement)
        return AnyView(self)
    }
        return AnyView(self)
    }

}

You could theoretically use this in a view like so:

struct ContentView: View {
    @State var popupEl:PopupElement?
    var body: some View {
        PopupPicker(selectedRow: $popupEl)
            .onSelection { element in
                print(element.name)
        }
        
    }
}

However I couldn't test it properly, please comment on your findings

Hope this could give you some insight in the workings of this, sorry if I couldn't give a full solution

Upvotes: 2

Related Questions