¿Cuál es la mejor manera de aprovechar las nuevas características de diseño automático de iOS 6 y al mismo tiempo proporcionar compatibilidad con dispositivos más antiguos en versiones anteriores de iOS?
¿Cuál es la mejor manera de aprovechar las nuevas características de diseño automático de iOS 6 y al mismo tiempo proporcionar compatibilidad con dispositivos más antiguos en versiones anteriores de iOS?
Respuestas:
Autolayout se puede habilitar o deshabilitar en cada archivo .storyboard o .xib. Simplemente seleccione el archivo en particular y modifique la propiedad "Usar Autolayout" usando el inspector de archivos en Xcode:
El uso de archivos de interfaz habilitados para autolayout con el objetivo de implementación establecido en una versión de iOS anterior a 6.0 produce errores de compilación, por ejemplo:
Error en MainStoryboard.storyboard: 3: Diseño automático en versiones de iOS anteriores a 6.0
Una de sus opciones para usar la distribución automática en un proyecto y aún preservar la compatibilidad con iOS4-5 es crear dos objetivos : uno para el objetivo de implementación de iOS 6.0 y otro para una versión anterior de iOS, por ejemplo:
También puede crear dos versiones para cada uno de sus archivos de guión gráfico y XIB y utilizar la distribución automática habilitada con el objetivo 6.0 y la otra con el objetivo heredado, por ejemplo:
Luego agrega MainStoryBoardAutoSize a las fases de compilación del objetivo iOS6 y el otro archivo al objetivo iOS4. Puede obtener más información sobre el uso de múltiples objetivos aquí .
EDITAR: Como señala la respuesta de marchinram , si carga los archivos del guión gráfico desde el código y no usa la configuración "Guión gráfico principal" en Xcode para establecer el guión gráfico inicial, puede usar un solo objetivo.
Para mí, el costo de la complejidad adicional de mantener múltiples objetivos y archivos de interfaz parece superar los beneficios del uso de la distribución automática. Excepto por algunos casos especiales, probablemente sea mucho mejor utilizar el tamaño automático antiguo (o layoutSubViews del código) exclusivamente si se requiere compatibilidad con iOS4-5.
¿Realmente necesitas dos objetivos? Lo hice funcionar así, tengo 2 guiones gráficos como dijo Imre Kelényi, uno con diseños automáticos habilitados y el otro sin ellos, luego en el delegado de la aplicación solo verifico qué versión 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 objetivos también funciona, pero me parece excesivo
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TO
Es exagerado. Simplemente pruebe una clase solo para iOS 6 contra cero. Ver developer.apple.com/library/mac/#documentation/developertools/…
Si las diferencias de diseño no son grandes, es mucho más fácil usar resortes y puntales para colocar elementos.
Inspirada en la única idea objetivo de @marchinram, esta es la solución que finalmente se me ocurrió. Dos guiones gráficos, uno para struts-and-springs y otro para autolayout. En el resumen de destino, configuré el guión gráfico de distribución automática como predeterminado. Luego, en appDelegate, verifico si necesito cargar el guión gráfico anterior de 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 objetivo de implementación del guión gráfico struts-and-springs en iOS 5.1, y el del guión gráfico de distribución automática en Project SDK (iOS 6.0).
Realmente quería hacer el cambio antes de que se cargue el valor predeterminado en storyboard, 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 usar RRAutoLayout: https://github.com/RolandasRazma/RRAutoLayout Es el backport de iOS6 AutoLayout para iOS5.