Есть ли событие изменения размера UIView? - PullRequest
94 голосов
/ 23 октября 2010

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

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

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

Ответы [ 7 ]

92 голосов
/ 23 октября 2010

Как прокомментировал Uli ниже, правильный способ сделать это - переопределить 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:
    }
}
84 голосов
/ 21 декабря 2014

В подклассе UIView могут использоваться наблюдатели свойств :

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

Без подклассов, наблюдение значения ключа с умным ключом-paths будет делать:

var boundsObservation: NSKeyValueObservation?

func beginObservingBounds() {
    boundsObservation = observe(\.bounds) { capturedSelf, _ in
        // ...
    }
}
28 голосов
/ 15 февраля 2011

Создание подкласса UIView и переопределение layoutSubviews

7 голосов
/ 07 декабря 2017

Swift 4 keypath KVO - так я обнаруживаю автоповорот и переход на боковую панель 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()
    //...
}
7 голосов
/ 24 апреля 2014

Довольно старый, но все еще хороший вопрос.В примере кода 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:.

6 голосов
/ 04 мая 2011

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

setFrame: (CGRect) рама

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

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

  // Do your custom code here.
}
0 голосов
/ 21 апреля 2017

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

override func viewDidLayoutSubviews() {
    // update subviews
}
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...