Skip to content

Instantly share code, notes, and snippets.

@PimCoumans
Last active February 8, 2024 09:57
Show Gist options
  • Select an option

  • Save PimCoumans/823b3fd1b428ff82e3ccd5567c885b40 to your computer and use it in GitHub Desktop.

Select an option

Save PimCoumans/823b3fd1b428ff82e3ccd5567c885b40 to your computer and use it in GitHub Desktop.

Revisions

  1. PimCoumans revised this gist Feb 8, 2024. 1 changed file with 1 addition and 1 deletion.
    2 changes: 1 addition & 1 deletion PrimaryActionHandler.swift
    Original file line number Diff line number Diff line change
    @@ -22,7 +22,7 @@ public protocol PrimaryActionSetting {
    /// The handler associated with a `UIAction` with the `.primary` identifier
    @MainActor var actionHandler: UIActionHandler? { get set }

    /// Updates 'primary' action set to the receiver
    /// Updates 'primary' action set to the receiver
    /// - Parameter handler: Handler executed with the primary action
    @MainActor func setActionHandler(_ handler: UIActionHandler?)
    }
  2. PimCoumans revised this gist Feb 8, 2024. 1 changed file with 53 additions and 13 deletions.
    66 changes: 53 additions & 13 deletions PrimaryActionHandler.swift
    Original file line number Diff line number Diff line change
    @@ -1,28 +1,68 @@
    import UIKit

    extension UIAction.Identifier {
    public extension UIAction.Identifier {
    static let primary = UIAction.Identifier(rawValue: "PrimaryAction")
    }

    protocol PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping UIActionHandler)
    }

    extension PrimaryActionSetting {
    static func actionWithHandler(_ handler: @escaping UIActionHandler) -> UIAction {
    fileprivate extension UIAction {
    var handler: UIActionHandler? {
    // Tiny bit sketchy: cast UIAction's "handler" value to a ObjC block
    typealias ActionHandlerBlock = @convention(block) (UIAction) -> Void
    let handler = value(forKey: "handler") as AnyObject
    return unsafeBitCast(handler, to: ActionHandlerBlock.self)
    }
    static func primary(_ handler: @escaping UIActionHandler) -> UIAction {
    UIAction(identifier: .primary, handler: handler)
    }
    }

    extension UIButton: PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping (UIAction) -> Void) {
    public protocol PrimaryActionSetting {
    @MainActor var primaryAction: UIAction? { get }

    /// The handler associated with a `UIAction` with the `.primary` identifier
    @MainActor var actionHandler: UIActionHandler? { get set }

    /// Updates 'primary' action set to the receiver
    /// - Parameter handler: Handler executed with the primary action
    @MainActor func setActionHandler(_ handler: UIActionHandler?)
    }

    extension UIControl: PrimaryActionSetting {
    public var primaryAction: UIAction? {
    var primaryAction: UIAction?
    // Find action that is set as primary
    enumerateEventHandlers { action, _, _, stop in
    guard action?.identifier == .primary else {
    return
    }
    primaryAction = action
    stop = true
    }
    return primaryAction
    }

    public var actionHandler: UIActionHandler? {
    get {
    primaryAction?.handler
    }
    set {
    setActionHandler(newValue)
    }
    }

    public func setActionHandler(_ handler: UIActionHandler?) {
    removeAction(identifiedBy: .primary, for: .touchUpInside)
    addAction(UIButton.actionWithHandler(handler), for: .touchUpInside)
    handler.map { addAction(.primary($0), for: .touchUpInside) }
    }
    }

    extension UIBarButtonItem: PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping UIActionHandler) {
    primaryAction? = UIBarButtonItem.actionWithHandler(handler)
    public var actionHandler: UIActionHandler? {
    get { primaryAction?.handler }
    set { setActionHandler(newValue) }
    }
    }

    public func setActionHandler(_ handler: ((UIAction) -> Void)?) {
    primaryAction = handler.map { .primary($0) }
    }
    }
  3. PimCoumans created this gist Nov 17, 2022.
    28 changes: 28 additions & 0 deletions PrimaryActionHandler.swift
    Original file line number Diff line number Diff line change
    @@ -0,0 +1,28 @@
    import UIKit

    extension UIAction.Identifier {
    static let primary = UIAction.Identifier(rawValue: "PrimaryAction")
    }

    protocol PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping UIActionHandler)
    }

    extension PrimaryActionSetting {
    static func actionWithHandler(_ handler: @escaping UIActionHandler) -> UIAction {
    UIAction(identifier: .primary, handler: handler)
    }
    }

    extension UIButton: PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping (UIAction) -> Void) {
    removeAction(identifiedBy: .primary, for: .touchUpInside)
    addAction(UIButton.actionWithHandler(handler), for: .touchUpInside)
    }
    }

    extension UIBarButtonItem: PrimaryActionSetting {
    func setActionHandler(_ handler: @escaping UIActionHandler) {
    primaryAction? = UIBarButtonItem.actionWithHandler(handler)
    }
    }