Задача C - Методы отражения и переопределения? - PullRequest
3 голосов
/ 07 июля 2011

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

// This should be a public method maybe a category to NSObject
- (void)overrideGetterMethod
{
   //somehow convert my original getter with lazyInitialize method
}

- (id)lazyInitialize
{
   if (!self)
   {
      self = [[self class] alloc] init];
   }
   return self;
}

Выше приведена реализация функциональности, а ниже - ее использование

@property (nonatomic, retain) SomeObject *someObject;

- (void)viewDidLoad
{
   [super viewDidLoad];
   [someObject overrideGetterMethod];

   // So when I call the following method if the object is nil it get's instantiated automatically
   [self.someObject doSomething]
}

Ответы [ 3 ]

1 голос
/ 07 июля 2011

Вы, кажется, принимаете странный шаблон, и я не могу не думать, что вы хотите достичь, вероятно, лучше сделать это с помощью более высокого уровня маршрута, такого как просто:

if(result) return result;

/* stuff to fill result and then return it here */

Прогноз ветвления долженпримите это незначительные затраты времени выполнения.

С учетом оговорки, вы заинтересованы в method_setImplementation (для установки IMP для метода), class_getMethodImplementation (чтобы получить IMP из класса и селектора) и и class_getInstanceMethod (чтобы получить метод из класса и селектора).Используя их, вы можете настроить данный метод так, чтобы он реагировал на любой селектор или селекторы, которые вы хотите во время выполнения.

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

1 голос
/ 08 июля 2011

Может быть, это может быть начало:

@interface NSObject (LazyKVC)
- (id)lazyValueForKey:(NSString *)key;
@end


@implementation NSObject (LazyKVC)

- (id)lazyValueForKey:(NSString *)key {
    id value = [self valueForKey:key];
    if (!value) {                                   
        // Now, look for the type of property named |key|.
        // To spare you the details of the @encode() string, use
        // [self typeOfPropertyNamed:key] - see link provided below

        NSString className = [NSString stringWithUTF8String:
                                 [self typeOfPropertyNamed:key]];

        Class propertyClass = NSClassFromString(className);

        if (propertyClass) {
            value = [[propertyClass alloc] init];
        }
    }
    return value;
}

@end    

Примечание:

  1. Приведенный выше код использует - (const char *)typeOfPropertyNamed:(NSString *)name, , доступное здесь .
  2. Я опустил угловые случаи (исправление ошибок и т. Д.).

Использование будет:

[foo lazyValueForKey:@"bar"];

Мне интересно, если вы можете заставить его работать так (я написал это прямо в окне браузера ...)

Примечание о внедрении (зависимости)

Чтобы ваш метод мог возвращать нужный объект во время выполнения (посредством внедрения), вам понадобится - в качестве начальной точки -следующее:

  1. файл конфигурации (чтобы указать lazyValueForKey:, откуда инициализировать внедренный объект, например, plist)
  2. соглашение: как вы будете называть этот файл конфигурации такlazyValueForKey: найдет его
  3. метод, который позволит вам искать и инициализировать объект из файла конфигурации (например, какие поля и атрибуты вы включите в файл конфигурации для описания объектов).
  4. изменить метод lazyValueForKey: для эффективной десериализации / чтения объектов из файла конфигурации

Обратите внимание, что пункты 1-2-3 выше могут привести вас к абстракцииданные внедрения зависимостиисточник, который будет управлять конфигурацией ваших внедренных объектов и предоставлять вам их во время выполнения.

Я, конечно, здесь упускаю другие важные моменты, но я считаю, что это начинает выходить за рамки вашего первоначального вопроса, поэтому я не буду продолжать с моим ответом.Реализация механизма внедрения зависимостей - нелегкая задача.Тем не менее, вы можете найти больше информации на этот хороший вопрос SO .

0 голосов
/ 07 июля 2011

Если я вас правильно понял, вы хотите что-то вроде этого:

-(SomeObject*) someObject {
    if( !mSomeObject ) {
        //initialize it
        mSomeObject = [[SomeObject alloc] init];
    }

    return mSomeObject;
}

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

...