Habilitar el diseño automático en iOS 6 mientras se mantiene compatible con versiones anteriores de iOS 5

¿Cuál es la mejor manera de aprovechar las nuevas características de diseño automático de iOS 6 y al mismo tiempo ofrecer compatibilidad con dispositivos más antiguos en versiones anteriores de iOS?

El diseño automático se puede habilitar o deshabilitar en cada archivo .storyboard o .xib. Simplemente seleccione el archivo en particular y modifique la propiedad “Usar ajuste automático” usando el inspector de archivos en Xcode:

propiedad de autolayout en el inspector de archivos

El uso de archivos de interfaz habilitados para el autodesplazamiento con el objective de implementación configurado en una versión de iOS anterior a la 6.0 da como resultado errores de comstackción, por ejemplo:

Error en MainStoryboard.storyboard: 3: diseño automático en versiones de iOS anteriores a 6.0

Una de las opciones para utilizar el autolayout en un proyecto y aún así conservar la compatibilidad con iOS4-5 es crear dos objectives : uno para el destino de implementación iOS 6.0 y otro para una versión anterior de iOS, por ejemplo:

enter image description here

También puede crear dos versiones para cada uno de sus storyboards y archivos XIB, y usar el autolayout habilitado con el destino 6.0 y el otro con el objective heredado, por ejemplo:

enter image description here

A continuación, agrega MainStoryBoardAutoSize a las fases de comstackción del objective iOS6 y el otro archivo al destino iOS4. Puede obtener más información sobre el uso de múltiples objectives aquí .

EDITAR: Como señala la respuesta de Marchinram , si carga los archivos del guión gráfico desde el código y no utiliza la configuración “Guión gráfico principal” en Xcode para establecer el guión gráfico inicial, puede usar un solo objective.

Para mí, el costo de la complejidad adicional de mantener múltiples objectives y archivos de interfaz parece superar los beneficios de usar el diseño automático. Excepto por algunos casos especiales, es probable que sea mucho mejor utilizar el tamaño auto antiguo simple (o layoutSubViews del código) exclusivamente si se requiere compatibilidad iOS4-5.

¿Realmente necesitas dos objectives? Lo conseguí trabajando así, tengo 2 guiones gráficos como Imre Kelényi, uno con diseños automáticos habilitados y el otro sin, luego, en el delegado de la aplicación solo comprobo la versión que están usando y selecciono el guión gráfico correcto:

#import "AppDelegate.h" #define SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(v) ([[[UIDevice currentDevice] systemVersion] compare:(v) options:NSNumericSearch] != NSOrderedAscending) @interface AppDelegate () @property (strong, nonatomic) UIViewController *initialViewController; @end @implementation AppDelegate @synthesize window = _window; - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { UIStoryboard *mainStoryboard = nil; if (SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO(@"6.0")) { mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS6" bundle:nil]; } else { mainStoryboard = [UIStoryboard storyboardWithName:@"iPhone_iOS5" bundle:nil]; } self.initialViewController = [mainStoryboard instantiateInitialViewController]; self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]]; self.window.rootViewController = self.initialViewController; [self.window makeKeyAndVisible]; return YES; } @end 

Tener 2 objectives también funciona pero me parece excesivo

Si las diferencias de diseño no son grandes, es mucho más fácil usar Resortes y Struts para colocar elementos.

Inspirada en la idea de objective de @marchinram, esta es la solución que finalmente se me ocurrió. Dos storyboards, uno para struts-and-springs y otro para autolayout. En el resumen de destino, configuré el guión gráfico de autodiseño como predeterminado. Luego, en la appDelegate, compruebo si necesito cargar el guión gráfico anterior a 6.0 struts-and-springs después de todo:

  - (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions { Class cls = NSClassFromString (@"NSLayoutConstraint"); if (cls == nil) { NSString *mainStoryboardName = nil; if ([[UIDevice currentDevice] userInterfaceIdiom] == UIUserInterfaceIdiomPad) { mainStoryboardName = @"MainStoryboard_iPad_StrutsAndSprings"; } else { mainStoryboardName = @"MainStoryboard_iPhone_StrutsAndSprings"; } UIStoryboard *mainStoryboard = [UIStoryboard storyboardWithName:mainStoryboardName bundle:nil]; UIViewController *initialViewController = [mainStoryboard instantiateInitialViewController]; self.window.rootViewController = initialViewController; [self.window makeKeyAndVisible]; } 

Además, configuré el destino de despliegue del guión gráfico de struts-springs en iOS 5.1 y el del storyboard de autolayout en Project SDK (iOS 6.0).

Realmente quería hacer el cambio antes de que se cargue el guión gráfico por defecto, en willFinishLaunchingWithOptions: pero eso da como resultado una ‘NSInvalidUnarchiveOperationException’, razón: ‘No se pudo crear una instancia de la clase llamada NSLayoutConstraint’ sin importar lo que intenté.

Intente utilizar RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayout Es iOS6 AutoLayout backport para iOS5.

He encontrado establecer el tamaño de vista principal de Xibs en Freeform, y luego usar el Autosizing funciona de maravilla. Sin problemas en el código para un problema de vista.