Вопрос

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

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

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

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

  ... do some stuff with the old result

    return result;
}

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

  

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

Это было полезно?

Решение

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

То, что вы хотите, называется метод Swizzling . Но имейте в виду, что ваш код может что-то сломать. На есть статья Theocacao, написанная Скоттом Стивенсоном о методе Swizzling в старой версии Objective-C, Мэтт Галлахер: «Какао с любовью» содержит статью о методе Swizzling в новой цели -C 2.0 время выполнения и простая замена для него.

Кроме того, вы можете создать подкласс класса и затем использовать его или использовать + (void) poseAsClass: (Class) aClass для замены суперкласса , Apple пишет:

  

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

Имейте в виду, что Apple не поддерживает poseAsClass: в Mac OS X 10.5.

Другие советы

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

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

  ... do some stuff with the old result

    return result;
}

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

Не совсем в категории, но есть обходной путь, добавляющий метод динамически во время выполнения. Сэмюэль D & # 233; fago в своей статье описывает изящный способ создания реализации IMP, вызывающей super, его оригинальную статью можно найти здесь

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

#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);
Лицензировано под: CC-BY-SA с атрибуция
Не связан с StackOverflow
scroll top