62
задан 16 September 2011 в 16:35

3 ответа

Swift 4

Здесь является быстрым Использованием решения

class ClosureSleeve {
let closure: () -> ()

init(attachTo: AnyObject, closure: @escaping () -> ()) {
    self.closure = closure
    objc_setAssociatedObject(attachTo, "[\(arc4random())]", self, .OBJC_ASSOCIATION_RETAIN)
}

@objc func invoke() {
    closure()
  }
}

extension UIControl {
func addAction(for controlEvents: UIControlEvents = .primaryActionTriggered, action: @escaping () -> ()) {
    let sleeve = ClosureSleeve(attachTo: self, closure: action)
    addTarget(sleeve, action: #selector(ClosureSleeve.invoke), for: controlEvents)
 }
}

В качестве примера:

button.addAction {
print("button pressed")
}
7
ответ дан 31 October 2019 в 13:56

Мне легко и универсальный для использования крошечного класса помощника:

@interface Handler : NSObject

@end

@implementation Handler {
    void (^block)(id);
}

+ (Handler *)create:(void (^)(id))block {
    Handler *result = [[Handler alloc] init];

    result->block = block;

    return result;
}

- (void)call:(id)sender {
    block(sender);
}

@end

и использование это как это:

Handler *handler = [Handler create:^(id sender) {
    // ... handle the event, using local state captured by the block ...
}];

// store the handler because the target is not retained in addTarget
[handlers addObject:handler];

[button addTarget:handler action:@selector(call:) forControlEvents:UIControlEventTouchUpInside];
1
ответ дан 31 October 2019 в 13:56

Быстрое расширение / основанная на категории реализация, которую я сделал на скорую руку. Используя связанные объекты OBJC не антишаблон. :P

import UIKit

// MARK: UIControl Block based actions
typealias ActionBlock = (UIControl) -> ()

class UIButtonActionDelegate : NSObject {
    let actionBlock : ActionBlock
    init(actionBlock: ActionBlock) {
        self.actionBlock = actionBlock
    }
    func triggerBlock(control : UIControl) {
        actionBlock(control)
    }
}

private var actionHandlersKey: UInt8 = 0
extension UIControl {
    var actionHandlers: NSMutableArray { // cat is *effectively* a stored property
        get {
            return associatedObject(self, key: &actionHandlersKey, initialiser: { () -> NSMutableArray in
                return NSMutableArray()
            })
        }
        set { associateObject(self, key: &actionHandlersKey, value: newValue) }
    }

    func addBlockForEvents(events: UIControlEvents, block: ActionBlock) {
        let actionDelegate = UIButtonActionDelegate(actionBlock: block)
        actionHandlers.addObject(actionDelegate) // So it gets retained
        addTarget(actionDelegate, action: #selector(UIButtonActionDelegate.triggerBlock(_:)), forControlEvents: events)
    }
}

// MARK: Associated Object wrapper

func associatedObject<ValueType: AnyObject>(
    base: AnyObject,
    key: UnsafePointer<UInt8>,
    initialiser: () -> ValueType)
    -> ValueType {
        if let associated = objc_getAssociatedObject(base, key)
            as? ValueType { return associated }
        let associated = initialiser()
        objc_setAssociatedObject(base, key, associated,
                                 .OBJC_ASSOCIATION_RETAIN)
        return associated
}

func associateObject<ValueType: AnyObject>(
    base: AnyObject,
    key: UnsafePointer<UInt8>,
    value: ValueType) {
    objc_setAssociatedObject(base, key, value,
                             .OBJC_ASSOCIATION_RETAIN)
}
0
ответ дан 31 October 2019 в 13:56

Другие вопросы по тегам:

Похожие вопросы: