Используйте механизм разрешения динамического метода, описанный в Руководстве по программированию Objective-C, в частности, +[NSObject resolveInstanceMethod:]
:
@implementation UINavigationController (FWD)
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
NSString *name = NSStringFromSelector(sel);
NSString *prefix = @"push";
NSString *suffix = @"Animated:";
if ([name hasPrefix:prefix] && [name hasSuffix:suffix]) {
NSRange classNameRange = {[prefix length],
[name length] - [prefix length] - [suffix length]}
NSString *className = [name substringWithRange:classNameRange];
Class cls = NSClassFromString(className);
if (cls) {
IMP imp = imp_implementationWithBlock(
^(id me, BOOL animated) {
id vc = [[cls alloc] init];
[me pushViewController:vc animated:animated];
[vc release];
});
class_addMethod(cls, sel, imp, "v@:c");
return YES;
}
}
return [super resolveInstanceMethod:sel];
}
@end
Конечно, если UINavigationController
уже использует +resolveInstanceMethod:
, вы его сломали. Выполнение этого в подклассе UINavigationController
или использование метода swizzling для включения вызова исходной реализации решит эту проблему.
Версия, принимающая блок после создания, является простым расширением (измените параметры блока, измените кодировку типа, измените шаблон имени селектора и способ извлечения предполагаемого имени класса).