Есть ли событие изменения размера UIView?


У меня есть представление, которое имеет строки и столбцы imageviews в нем.

Если это представление изменяется, мне нужно изменить позиции imageviews.

Это представление является подвидом другого представления, размер которого изменяется.

есть ли способ определить, когда это представление изменяется?

7 80

7 ответов:

а Ули прокомментировал ниже, правильный способ сделать это переопределить layoutSubviews и макет imageViews там.

если по какой-то причине вы не можете подкласс и переопределить layoutSubviews, наблюдая bounds должен работать, даже когда он грязный. Хуже того, есть риск с наблюдением - Apple не гарантирует, что KVO работает на классах UIKit. Читайте обсуждение с инженером Apple здесь:когда освобождается Связанный объект?

оригинал ответ:

вы можете использовать ключ-значение наблюдений:

[yourView addObserver:self forKeyPath:@"bounds" options:0 context:nil];

и реализуем:

- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object change:(NSDictionary *)change context:(void *)context
{
    if (object == yourView && [keyPath isEqualToString:@"bounds"]) {
        // do your stuff, or better schedule to run later using performSelector:withObject:afterDuration:
    }
}

на UIView подкласс, наблюдатели собственность можно использовать в:

override var bounds: CGRect {
    didSet {
        // ...
    }
}

без разделения на подклассы,

создать подкласс UIView и переопределить layoutSubviews

Swift 4 keypath KVO -- вот как я обнаруживаю autorotate и перемещение на боковую панель iPad. Должна работать работа любого вида. Пришлось наблюдать за слоем UIView.

private var observer: NSKeyValueObservation?

override func viewDidLoad() {
    super.viewDidLoad()
    observer = view.layer.observe(\.bounds) { object, _ in
        print(object.bounds)
    }
    // ...
}
override func viewWillDisappear(_ animated: Bool) {
    observer?.invalidate()
    //...
}

вы можете создать подкласс UIView и переопределить

setFrame: (CGRect)frame

метод. Это метод, вызываемый при изменении кадра (т. е. размера) представления. Сделать что-то вроде этого:

- (void) setFrame:(CGRect)frame
{
  // Call the parent class to move the view
  [super setFrame:frame];

  // Do your custom code here.
}

довольно старый, но все же хороший вопрос. В примере кода Apple и в некоторых из их частных подклассов UIView они переопределяют setBounds примерно так:

-(void)setBounds:(CGRect)newBounds {
    BOOL const isResize = !CGSizeEqualToSize(newBounds.size, self.bounds.size);
    if (isResize) [self prepareToResizeTo:newBounds.size]; // probably saves 
    [super setBounds:newBounds];
    if (isResize) [self recoverFromResizing];
}

переопределение setFrame: не очень хорошая идея. frame происходит от center,bounds и transform, так что iOS не обязательно называть setFrame:.

Если вы находитесь в экземпляре UIViewController, переопределение viewDidLayoutSubviews делает трюк.

override func viewDidLayoutSubviews() {
    // update subviews
}