Подтвердить что ты не робот

Переопределить метод через ObjC Category и вызвать реализацию по умолчанию?

При использовании категорий вы можете переопределить методы реализации со своим собственным, например:

// Base Class 
@interface ClassA : NSObject 
- (NSString *) myMethod;
@end
@implementation ClassA
- (NSString*) myMethod { return @"A"; }
@end

//Category
@interface ClassA (CategoryB) 
- (NSString *) myMethod;
@end
@implementation ClassA (CategoryB)
- (NSString*) myMethod { return @"B"; }
@end

Вызов метода "myMethod" после включения категории устанавливает результат "B".

Что является самым простым способом для реализации класса myMethod для вызова исходного класса myMethod? Насколько я могу судить, вам придется использовать вызовы низкого уровня, чтобы получить первоначальный метод hook для класса A и назвать это, но казалось, что это будет синтаксически более простой способ сделать это.

4b9b3361

Ответ 1

Если вам нужен хакерский способ сделать это, связанный с запуском среды objective-c, вы всегда можете использовать метод

Ответ 2

Из comp.lang.objective-C Часто задаваемые вопросы: " Что делать, если несколько категорий реализуют один и тот же метод? Тогда ткань Вселенной, как мы ее знаем, перестает существовать. На самом деле это не совсем верно, но, конечно, некоторые проблемы будут вызваны. Когда категория реализует метод, который уже появился в классе (будь то через другую категорию или class 'primary @implementation), это определение категории перезаписывает ранее существующее определение. Исходное определение больше не может быть достигнуто с помощью кода Objective-C. Обратите внимание, что если две категории перезаписывают один и тот же метод, то какой бы ни был загружен последний" выигрывает ", что может быть невозможно предсказать до запуска кода."

Из developer.apple.com: "Когда категория переопределяет унаследованный метод, метод в категории может, как обычно, вызывать унаследованную реализацию через сообщение для супер. Однако, если категория переопределяет метод, который уже существовал в классе категории, нет способа вызвать исходную реализацию"

Ответ 3

Ознакомьтесь с моей статьей о решении, найденном в Mac Developer Library: http://codeshaker.blogspot.com/2012/01/calling-original-overridden-method-from.html

В принципе, это так же, как вышеописанный метод Swizzling с кратким примером:

#import <objc/runtime.h>

@implementation Test (Logging)

- (NSUInteger)logLength {
    NSUInteger length = [self logLength];
    NSLog(@"Logging: %d", length);
    return length;
}

+ (void)load {
    method_exchangeImplementations(class_getInstanceMethod(self, @selector(length)), class_getInstanceMethod(self, @selector(logLength)));
}

@end

Ответ 4

С помощью swizzling "вспомогательных" методов, включенных в ConciseKit, вы фактически вызываете реализацию по умолчанию... странно достаточно..., вызвав ваш SWIZZLED осуществление..

Вы установите его в + (void) load, вызывая + (BOOL)swizzleMethod:(SEL)originalSelector with:(SEL)anotherSelector in:(Class)klass;, i.e.

[$ swizzleMethod:@selector(oldTired:) 
            with:@selector(swizzledHotness:) in:self.class];

а затем в swizzled method.. пусть предположим, что он возвращает -(id).. вы можете сделать свое зло или какую бы то ни было причину, которую вы в первую очередь запустили... а затем вместо возвращения объекта или self, или что-то еще.

return [self swizzledHotness:yourSwizzledMethodsArgument];

Как объясняется здесь...

В этом методе похоже, что мы снова вызываем тот же метод, вызываем и бесконечную рекурсию. Но к тому времени, когда эта линия будет достигнута, оба метода были заменены. Поэтому, когда мы вызываем swizzled_synchronize, мы на самом деле вызываем оригинальный метод.

Он чувствует и выглядит странно, но.. он работает. Это позволяет добавлять бесконечные приукрашивания к существующим методам и по-прежнему "называть супер" (на самом деле "я" ) и использовать преимущества первоначального метода handiwork... даже без доступа к исходному источнику.