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

Использование Super в объектной категории C?

Я хотел бы переопределить метод в классе Objective C, для которого у меня нет источника.

Я просмотрел его, и кажется, что Категории должны позволить мне сделать это, но я хотел бы использовать результат старого метода в моем новом методе, используя super, чтобы получить результат старых методов.

Всякий раз, когда я пытаюсь это сделать, мой метод вызывается, но "супер" - это ноль... Любая идея, почему? Я занимаюсь разработкой iPhone с помощью SDK XCode 2.2. Я определенно работаю с экземпляром класса, а метод класса - это метод экземпляра.

@implementation SampleClass (filePathResolver)
-(NSString*) fullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [super fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

Примечание и разъяснение. Из чего я могу видеть в Документах Apple, мне кажется, что это должно быть разрешено?

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

4b9b3361

Ответ 1

Категории расширяют исходный класс, но не подклассифицируют его, поэтому вызов super не находит метод.

Что вы хотите, называется Метод Swizzling. Но имейте в виду, что ваш код может что-то сломать. Там статья о Theocacao, написанная шотландец Стивенсоном о методе Swizzling в старой среде Objective-C, Cocoa с любовью Matt Gallagher содержит статью о методе Swizzling в новой версии Objective-C 2.0 и простой замене для нее.

В качестве альтернативы вы можете подклассифицировать класс, а затем либо использовать подкласс, либо использовать + (void)poseAsClass:(Class)aClass для замены суперкласса. Apple пишет:

Метод, определяемый классом позирования может, через сообщение super, включить метод суперкласса переопределение.

Помните, что Apple отказалась от poseAsClass: в Mac OS X 10.5.

Ответ 2

Если вы будете кодировать этот класс, просто переименуйте селектор на то, что может использовать ваш код, и вызовите исходный селектор на self:

@implementation SampleClass (filePathResolver)
-(NSString*) myFullPathFromRelativePath:(NSString*) relPath
{
    NSString *result = [self fullPathFromRelativePath: relPath];

  ... do some stuff with the old result

    return result;
}

Если вы хотите переопределить реализацию этого селектора по умолчанию для этого класса, вам нужно будет использовать метод swizzling.

Ответ 3

Не точно в категории, но есть обходное решение, динамически добавляя метод во время выполнения. Самюэль Дефаго в своей статье описывает аккуратный способ создания блочной IMP-реализации, вызывающей супер, его оригинальную статью можно найти здесь

Соответствующий код:

#import <objc/runtime.h>
#import <objc/message.h>

    const char *types = method_getTypeEncoding(class_getInstanceMethod(clazz, selector));
    class_addMethod(clazz, selector, imp_implementationWithBlock(^(__unsafe_unretained id self, va_list argp) {
        struct objc_super super = {
            .receiver = self,
            .super_class = class_getSuperclass(clazz)
        };

        id (*objc_msgSendSuper_typed)(struct objc_super *, SEL, va_list) = (void *)&objc_msgSendSuper;
        return objc_msgSendSuper_typed(&super, selector, argp);
    }), types);