Цель C: метод объекта Swizzle после создания - PullRequest
2 голосов
/ 30 марта 2012

Я бы хотел использовать метод объекта после его создания.

Пример:

@interface MyObj: NSObject
-(NSString*) foo;
-(NSString*) bar;
@end

@implementation MyObj
-(NSString*) foo {return @"foo";}
-(NSString*) bar {return @"bar";}
@end

void Swizzle(object, SEL source, SEL, dest);

...

MyObj* obj = [[[MyObj alloc] init] autorelease];

NSLog(@"%@", [obj foo]);
Swizzle(obj, @selector(foo), @selector(bar));
NSLog(@"%@", [obj foo]);

Вывод:

foo
bar

Я просмотрел множество примеров мерцания перед созданием объекта.Однако, как вы можете видеть, я хочу кружиться после создания объекта.

Это потому, что я хочу отслеживать объекты, которые собираются выпустить (например, NSThread).Я не хочу ругать NSObject dealloc, потому что это кажется излишним.Я предпочел бы кружить только объекты, которые я пытаюсь отследить.

Ответы [ 3 ]

3 голосов
/ 30 марта 2012

Это, честно говоря, похоже на необдуманную попытку избежать использования инструментов.Если это так, правильный ответ - «Просто используйте инструменты».

Но чтобы ответить на вопрос: вы не можете сделать это с отдельными объектами.Методы - даже методы экземпляра - определяются для каждого класса, а не для каждого объекта.Единственный способ переопределить метод для каждого объекта - динамически создать подкласс класса объекта, который переопределяет интересующий вас метод, и is-swizzle объекта, чтобы он использовал таблицу поиска подкласса.(Это в основном то, как KVO делает свои волшебные уведомления под капотом.) Опять же, это немного взломать и, как правило, гораздо больше проблем, чем стоит, поэтому, прежде чем вы сделаете это, я бы действительно подумал дважды (или три раза).) о том, действительно ли это необходимо.Почти для любого случая использования, который я могу придумать, есть более чистый способ достижения той же цели, который не включает в себя voodoo времени выполнения.

1 голос
/ 30 марта 2012

Нельзя проносить объект, только определенный класс. Кроме того, реализация для селектора кэшируется, и этот кэш может не очищаться автоматически при перевороте, что означает, что новый метод не используется.

Я бы предложил переопределить (или быстро) dealloc в классе, который вы хотите отслеживать, и использовать свойство, чтобы определить, должен ли выполняться код отслеживания.

@property (nonatomic) BOOL shouldTrackDealloc;

@synthesize shouldTrackDealloc;
- (void)dealloc {
    if(self.shouldTrackDealloc) {
        NSLog(@"dealloc of %@",self);
    }
    ...
}

Если вы отслеживаете классы каркаса, вы не сможете использовать @synthesize, поскольку переменная экземпляра не будет в нужном классе, но вместо этого вы можете использовать связанные ссылки .

0 голосов
/ 09 августа 2012

Решение, которое я выбрал, заключалось в использовании objc_setAssociatedObject (поток, ключ, объект, OBJC_ASSOCIATION_RETAIN_NONATOMIC);

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

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...