Why is the new iOS 14 UIControl action syntax so terrible?

830 Views Asked by At

New in iOS 14, we can attach an action handler directly to a UIControl:

    let action = UIAction(title:"") { action in
        print("howdy!")
    }
    button.addAction(action, for: .touchUpInside)

That's cool in its way, but the syntax is infuriating. I have to form the UIAction first. I have to give the UIAction a title, even though that title will never appear in the interface. Isn't there a better way?

1

There are 1 best solutions below

0
On BEST ANSWER

First, you don't need to supply the title. This is (now) legal:

    let action = UIAction { action in
        print("howdy!")
    }
    button.addAction(action, for: .touchUpInside)

Second, you don't really need the separate line to define the action, so you can say this:

    button.addAction(.init { action in
        print("howdy!")
    }, for: .touchUpInside)

However, that's still infuriating, because now I've got a closure in the middle of the addAction call. It ought to be a trailing closure! The obvious solution is an extension:

extension UIControl {
    func addAction(for event: UIControl.Event, handler: @escaping UIActionHandler) {
        self.addAction(UIAction(handler:handler), for:event)
    }
}

Problem solved! Now I can talk the way I should have been permitted to all along:

    button.addAction(for: .touchUpInside) { action in
        print("howdy!")
    }

[Extra info: Where's the sender in this story? It's inside the action. UIAction has a sender property. So in that code, action.sender is the UIButton.]