Подход Арумана хорош, но он, вероятно, слишком сильно зависит от времени выполнения. Помимо проблем с производительностью, Swizzling и использование initialize
более восприимчивы к ошибкам, если кто-то еще хочет поиграть со временем выполнения одновременно. Я предлагаю использовать макросы C.
Определите эти макросы в верхней части вашего класса (или где угодно, на самом деле):
typedef void(^BlockAction)(id sender);
#define BlockActionProperty(ACTION) @property (copy) BlockAction ACTION;\
- (IBAction) ACTION:(id)sender;
#define BlockActionSynthesize(ACTION) @synthesize ACTION;\
- (IBAction) ACTION:(id)sender {\
if (ACTION) ACTION(sender);\
}
Теперь, чтобы создать новое действие, все, что вам нужно сделать, это заменить @property ...
в заголовке следующим (например):
BlockActionProperty(testAction);
и "синтезировать" его в реализации:
BlockActionSynthesize(testAction);
В любое время, если вы хотите переопределить это и использовать обычный метод действия, все, что вам нужно, это синтезировать и реализовать действие как обычно.
Это быстрее (и, на мой взгляд, чище), чем делать это во время выполнения, и, поскольку IBAction
определен, Interface Builder может "увидеть" его определение.