¿Hay un evento de cambio de tamaño de UIView?

Tengo una vista que tiene filas y columnas de imágenes en ella.

Si se cambia el tamaño de esta vista, necesito reorganizar las posiciones de las imágenes.

Esta vista es una subvista de otra vista que cambia de tamaño.

¿Hay alguna forma de detectar cuándo se cambia el tamaño de esta vista?

Como Uli comentó a continuación, la forma correcta de hacerlo es anular la distribución de las presentaciones y el diseño de las imageViews allí.

Si, por alguna razón, no puede subclasificar y anular las layoutSubviews , la observación de los bounds debería funcionar, incluso estando un poco sucia. Peor aún, existe un riesgo al observar: Apple no garantiza que KVO funcione en las clases de UIKit. Lea la discusión con el ingeniero de Apple aquí: ¿ Cuándo se libera un objeto asociado?

respuesta original:

Puede usar la observación del valor clave:

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

e implementar:

 - (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: } } 

En una subclase UIView , se pueden usar observadores de propiedad :

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

Sin subclases, la observación del valor -clave con rutas clave inteligentes hará:

 var boundsObservation: NSKeyValueObservation? func beginObservingBounds() { boundsObservation = observe(\.bounds) { capturedSelf, _ in // ... } } 

Crear subclase de UIView y anular layoutSubviews

Puede crear una subclase de UIView y anular la

setFrame: marco (CGRect)

método. Este es el método llamado cuando se cambia el marco (es decir, el tamaño) de la vista. Haz algo como esto:

 - (void) setFrame:(CGRect)frame { // Call the parent class to move the view [super setFrame:frame]; // Do your custom code here. } 

Bastante viejo, pero sigue siendo una buena pregunta. En el código de ejemplo de Apple, y en algunas de sus subclases privadas UIView, anulan setBounds más o menos como sigue:

 -(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: NO es una buena idea. frame se deriva de center , bounds y transform , por lo que iOS no necesariamente llamará a setFrame:

Swift 4 keypath KVO: así es como detecto la autorotación y me muevo al panel lateral del iPad. Debería funcionar el trabajo desde cualquier punto de vista. Tuve que observar la capa de 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() //... } 

Si se encuentra en una instancia de UIViewController, la anulación de viewDidLayoutSubviews hace el truco.

 override func viewDidLayoutSubviews() { // update subviews }