¿Puedo usar setFrame y autolayout en la misma vista?

Quiero agregar relleno a todos mis botones, así que subclassicé UIButton, y entre otros cambios, quería agregar un relleno fijo mediante el uso del método setFrame. Todo estaba funcionando, a excepción de setFrame. Revisé, y descubrí que si desactivo “usar AutoLayout” en esa vista, entonces puedo usar setFrame, y funciona. ¿Hay alguna forma de evitar esto? Realmente quiero usar el diseño automático, ya que ayuda a que la aplicación se vea bien tanto en dispositivos iPhone 5 como en dispositivos anteriores. Pero también me gustaría usar setFrame en mi subclase, para hacer mi vida un poco más fácil.

Resumiendo, mi pregunta es: ¿Puedo usar el diseño automático y también ajustar el marco de un UIView mediante progtwigción?

Si, esto se puede hacer.

Si establece una translatesAutoresizingMaskIntoConstraints = YES de translatesAutoresizingMaskIntoConstraints = YES , las llamadas a setFrame: se traducen automáticamente en tiempo de ejecución en restricciones de diseño basadas en el actualizingMask actual de la autoresizingMask . Esto le permite combinar el diseño basado en marcos con el diseño basado en restricciones.

Por ejemplo, podría usar Diseño automático para definir el diseño de todas las subvistas de una vista, pero aún llamar a setFrame: para establecer el tamaño y la posición de la vista. Desde su perspectiva, está haciendo el diseño con una combinación de diseño automático y manipulación directa de cuadros. Pero el sistema está usando restricciones para manejar todo.

Sin embargo, hay una gran advertencia sobre el uso de translatesAutoresizingMaskIntoConstraints .

Cuando hace esto, aún necesita asegurarse de que estas restricciones automáticas se puedan satisfacer con el rest de sus restricciones .

Entonces, por ejemplo, supongamos que ya existen restricciones que determinan el tamaño y la posición de su vista, y luego también establece las translatesAutoresizingMaskIntoConstraints = YES y llamó a setFrame: La llamada a setFrame: generará nuevas restricciones en la vista, que probablemente entren en conflicto con las restricciones ya existentes.

(De hecho, este error ocurre a menudo. Si alguna vez ve un mensaje de registro quejándose de restricciones conflictivas, y una de esas restricciones es una NSAutoresizingMaskLayoutConstraint , entonces lo que está viendo es un conflicto con una restricción automática. Este es un error fácil, porque translatesAutoresizingMaskIntoConstraints = YES es el valor predeterminado, por lo que si está configurando restricciones en el código, debe recordar apagarlo si no desea estas restricciones automáticas).

Por el contrario, suponga nuevamente que ya existen restricciones que determinan el tamaño y la posición de su vista, pero luego establece setFrame: translatesAutoresizingMaskIntoConstraints = NO antes de llamar a setFrame: En este caso, su setFrame: llamadas no produciría nuevas restricciones, por lo que no habría conflicto entre las restricciones por separado . Sin embargo, en este caso, todavía hay un “conflicto” entre las restricciones y el valor de marco que establezca . La próxima vez que se invoque Diseño automático, verá las restricciones ya existentes en la vista, calculará el valor de cuadro que requiera y establecerá el marco en el valor requerido, lo que destruirá el valor que estableció manualmente.

Para obtener más detalles, consulte la sección “Adoptar el diseño automático” en la Guía de diseño automático de Cocoa de Apple.

Lo que resultó ser lo más fácil para mí fue quitar la vista que quería mover / cambiar de tamaño desde su super visión, establecer su frame y luego volver a agregarlo. Por ejemplo, tome una UILabel personalizada en una subclase UITableViewCell :

 [cell.myLabel removeFromSuperview]; cell.myLabel.frame = someFrameIGenerated; [cell.contentView addSubview:cell.myLabel]; 

Algo que funcionó para mí fue simplemente agregar un IBOutlet para mis restricciones al controlador de visualización, y luego cambiar la propiedad de constant en la salida.

Por ejemplo, para cambiar el origen x de una vista, configure una salida desde la restricción principal de esa vista a su controlador. En otras palabras, crea una salida @IBOutlet var labelXOrigin: NSLayoutConstraint! . Luego, cuando quiera ajustar la posición x, simplemente haga algo como

 self.labelXOrigin.constant = 20.0 // Or whatever origin you want to set. 

La mejor manera de establecer el marco de la vista secundaria es el método viewWillLayoutSubviews en los proyectos de autolayout.

set property translatedAttoresizingMaskIntoConstraints = true esto funcionará después de que aparezca la vista o botón de tabulación para establecerlo, justo después de que aparezca la vista.

Si su aplicación no es compatible con orientaciones de dispositivos múltiples.

En viewDidLoad establece el marco de la vista que desea cambiar el tamaño

 - (void)viewDidLoad { [super viewDidLoad]; // Do any additional setup after loading the view. [aView setFrame:CGRectMake(15, 15, 100, 100)]; } 

Luego en viewDidLayoutSubviews :

 -(void)viewDidLayoutSubviews { [self.view setTranslatesAutoresizingMaskIntoConstraints:NO]; } 

No estoy seguro, pero creo que si usa esta solución, cambiar una orientación a otra podría causar problemas