Swizzling initWithFrame: не работает для объектов в острие

#objective-c #swizzling

#objective-c #перебирающий

Вопрос:

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

   (void) swizzleMethodsForFooCategory
{
    SwizzleInstanceMethods(self, @selector(initWithFrame:), @selector(foo_initWithFrame:));
    SwizzleInstanceMethods(self, @selector(dealloc), @selector(foo_dealloc));
}

- (id) foo_initWithFrame: (CGRect) frame
{
    NSLog(@"foo_initWithFrame: called");
    self = [self foo_initWithFrame: frame];
    if (self != nil)
    {
        NSNotificationCenter * center = [NSNotificationCenter defaultCenter];
        [center addObserver: self
                   selector: @selector(foo_connectionDidSucceed)
                       name: @"PM_connectionDidSucceed"
                     object: nil];
        [center addObserver: self
                   selector: @selector(foo_didDisconnect)
                       name: @"PM_didDisconnect"
                     object: nil];
    }
    return self;
}

- (void) foo_dealloc
{
    NSLog(@"foo_dealloc called");
    [[NSNotificationCenter defaultCenter] removeObserver: self name: @"PM_connectionDidSucceed" object: nil];
    [[NSNotificationCenter defaultCenter] removeObserver: self name: @"PM_didDisconnect" object: nil];
    [self foo_dealloc];
}

- (void) foo_connectionDidSucceed
{
    // Add gesture recognizers.
}

- (void) foo_didDisconnect
{
    // Remove gesture recognizers.
}
  

Это отлично работает для представлений, которые я создаю в коде, но если я объявляю их в XIB, мои методы не вызываются. Я использую swizzling вместо наследования, потому что я не хочу жестко кодировать эту поддержку — я хочу иметь возможность добавлять ее для каждой цели.

Что я могу сделать, чтобы подключить эти объекты, чтобы я мог добавить свои средства распознавания жестов для всех объектов этих типов, создаю ли я их программно или в NIB?

Ответ №1:

Просмотр объектов, созданных из использования NIB -initWithCoder: для инициализации, поэтому я бы попробовал использовать это вместо.

Комментарии:

1. Потрясающе! Большое спасибо за добавление еще одного лакомого кусочка в мою версию iOS.

2. ПРИМЕЧАНИЕ: Bavarious может быть более подходящим для материалов, которые не соответствуют NSCoding .

3. Неуправляемые объекты nib, получающие либо -initWithCoder: , либо -init описано в Руководстве по программированию ресурсов .

Ответ №2:

В iOS каждый объект, загруженный из файла nib, получает либо -initWithCoder: (если соответствующий класс соответствует NSCoding протоколу), либо -init (если соответствующий класс не соответствует NSCoding протоколу) при удалении из файла nib. Это отличается от Mac OS X, где пользовательские представления получают -initWithFrame: , а другие объекты получают либо -initWithCoder: , либо -init .

Поскольку ваши классы наследуются от UIView , что соответствует NSCoding протоколу, вам нужно swizzle -initWithCoder: .