Наблюдение за изменениями в окне UIView и свойствах суперпредставления - PullRequest
24 голосов
/ 10 апреля 2011

Я ищу способ получать уведомления, когда универсальный UIView добавляется или удаляется из иерархии видимого представления. KVO выглядело как идеальная вещь для использования в этом случае, но наблюдение за изменениями окна представления или свойств суперпредставления ничего не делает. Изменения в свойствах, таких как frame или backgroundColor, работают должным образом, но изменения в свойствах, относящихся к иерархии представлений, по-видимому, никогда не вызывают НаблюдатьValueForKeyPath.

Я проверил, поддерживает ли UIView KVO для этих свойств, вызвав automaticNotifiesObserversForKey, и UIView сообщил о YES обоим, что привело меня в замешательство. Итак, мои вопросы:

1) Есть ли способ использовать KVO для уведомления о событиях, связанных с добавлением / удалением представления в иерархию представлений?

2) Если нет, есть ли другой способ получать уведомления о таких событиях, которые не связаны с подклассом UIView?

Ответы [ 4 ]

11 голосов
/ 05 апреля 2013

Переопределить этот метод:

- (void)didMoveToSuperview
{
  UIView *superView = [self superview];
}

И вы можете переопределить эти методы в своем пользовательском представлении для другого использования:

- (void)willMoveToSuperview:(UIView *)newSuperview;
- (void)didMoveToSuperview;
- (void)willMoveToWindow:(UIWindow *)newWindow;
- (void)didMoveToWindow;
10 голосов
/ 09 апреля 2012

Вот способ.Это брутто?Да.Я рекомендую такое поведение?Нет. Но мы все здесь взрослые.

Суть в том, что вы используете method_setImplementation, чтобы изменить реализацию - [UIView didAddSubview:], чтобы вы получали уведомление всякий раз, когда он вызывается (и вы делаете то же самоедля воли Удалите Sububview :).К сожалению, вас будут вызывать для всех изменений иерархии представлений.Вам нужно будет добавить свою собственную фильтрацию, чтобы найти нужные вам виды.

static void InstallAddSubviewListener(void (^listener)(id _self, UIView* subview))
{
    if ( listener == NULL )
    {
        NSLog(@"listener cannot be NULL.");
        return;
    }

    Method addSubviewMethod = class_getInstanceMethod([UIView class], @selector(didAddSubview:));
    IMP originalImp = method_getImplementation(addSubviewMethod);

    void (^block)(id, UIView*) = ^(id _self, UIView* subview) {
        originalImp(_self, @selector(didAddSubview:), subview);
        listener(_self, subview);
    };

    IMP newImp = imp_implementationWithBlock((__bridge void*)block);
    method_setImplementation(addSubviewMethod, newImp);
}

Чтобы использовать, сделайте что-то вроде:

InstallAddSubviewListener(^(id _self, UIView *subview) {
    NSLog(@"-[UIView didAddSubview:]   self=%@, view=%@", _self, subview);
});
2 голосов
/ 20 июня 2012

на основе кода @ doug-richardson, почему бы не что-нибудь немного чище, которое позволит KVO для свойства superview?

//Make views announce their change of superviews
    Method method = class_getInstanceMethod([UIView class], @selector(willMoveToSuperview:));
    IMP originalImp = method_getImplementation(method);

    void (^block)(id, UIView*) = ^(id _self, UIView* superview) {
        [_self willChangeValueForKey:@"superview"];
        originalImp(_self, @selector(willMoveToSuperview:), superview);
        [_self didChangeValueForKey:@"superview"];
    };

    IMP newImp = imp_implementationWithBlock((__bridge void*)block);
    method_setImplementation(method, newImp);
1 голос
/ 11 февраля 2019

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

Написано на С, чтобы было легко понять и быстро.Вы можете изменить их так, чтобы они представляли собой некоторые гладкие категории NSObject.

Пример использования:

add_superview_kvo(UILabel.class);

Тогда вам придется добавить своего собственного наблюдателя к экземплярам в соответствии с обычным использованием.1009 *

...