Activation de la disposition automatique dans iOS 6 tout en restant rétrocompatible avec iOS 5

153

Quelle est la meilleure façon de profiter des nouvelles fonctionnalités de mise en page automatique d'iOS 6 tout en offrant une compatibilité avec les appareils plus anciens sur les versions antérieures d'iOS?

sglantz
la source
+1. Où avez-vous pu comprendre cela? Un indice?
Janak Nirmal
@Jennis Pas encore. iOS 6 sortira officiellement demain (19/09/2012). J'espère que cela comprend une documentation supplémentaire sur le sujet.
sglantz
Je n'ai encore rien trouvé. Les esprits curieux aimeraient savoir!
Ben Kreeger
Je ne pense pas que ce serait possible. Tout comme les storyboards n'étaient pas possibles sur iOS4.
Leo Natan
En dehors de fournir deux fichiers nib, je ne vois pas comment cela serait possible. Mais je suis d'accord avec toi.
Leo Natan

Réponses:

120

La mise en page automatique peut être activée ou désactivée sur chaque fichier .storyboard ou .xib. Sélectionnez simplement le fichier particulier et modifiez la propriété "Utiliser la mise en page automatique" à l'aide de l'inspecteur de fichiers dans Xcode:

propriété autolayout dans l'inspecteur de fichiers

L'utilisation de fichiers d'interface activés pour la mise en page automatique avec la cible de déploiement définie sur une version iOS antérieure à 6.0 entraîne des erreurs de compilation, par exemple:

Erreur dans MainStoryboard.storyboard: 3: Disposition automatique sur les versions iOS antérieures à 6.0

L'une de vos options pour utiliser la mise en page automatique dans un projet tout en préservant la compatibilité avec iOS4-5 consiste à créer deux cibles : une pour la cible de déploiement iOS 6.0 et une pour une version iOS antérieure, par exemple:

entrez la description de l'image ici

Vous pouvez également créer deux versions pour chacun de vos fichiers storyboard et XIB et utiliser la mise en page automatique activée avec la cible 6.0 et l'autre avec la cible héritée, par exemple:

entrez la description de l'image ici

Vous ajoutez ensuite MainStoryBoardAutoSize aux phases de construction de la cible iOS6 et l'autre fichier à la cible iOS4. Vous pouvez en savoir plus sur l'utilisation de plusieurs cibles ici .

EDIT: Comme le souligne la réponse de marchinram , si vous chargez vos fichiers de storyboard à partir du code et n'utilisez pas le paramètre "Main Storyboard" dans Xcode pour définir le storyboard initial, vous pouvez utiliser une seule cible.

Pour moi, le coût de la complexité supplémentaire de la maintenance de plusieurs cibles et fichiers d'interface semble l'emporter sur les avantages de l'utilisation de la mise en page automatique. À l'exception de quelques cas particuliers, il est probablement préférable d'utiliser le dimensionnement automatique (ou layoutSubViews à partir du code) exclusivement si la compatibilité iOS4-5 est requise.

Imre Kelényi
la source
29
La disposition automatique nécessite iOS 6 ou version ultérieure. Cela ne fonctionne pas avec iOS 5! Veuillez vérifier vos réclamations avant de publier. iOS 5 n'a tout simplement pas les API requises (telles que la classe NSLayoutConstraint). Si vous ne me croyez pas, découvrez ce que vivent les autres utilisateurs lorsqu'ils essaient d'utiliser la mise en page automatique avec iOS 5: stackoverflow.com/questions/11252057/… stackoverflow.com/questions/11198981/…
Imre Kelényi
1
Oui, je pense que vous avez raison, je pense que je l'ai entendu dans certaines vidéos wwdc, mais maintenant je l'ai testé sur un appareil iOS 5.0 et il s'est écrasé. Je vais parcourir ces vidéos et vérifier où je l'ai entendu.Cependant, vous avez raison, il plante sur iOS 5.0
Asad Khan
@ ImreKelényi Comment soumettriez-vous cela à l'App Store? Je ne suis pas très familier avec le processus, mais je pensais que vous soumettiez une archive compressée de votre fichier .app. Le fait d'avoir deux cibles rend-il ce processus plus difficile du tout? Merci.
Crystal
47

Avez-vous vraiment besoin de deux cibles? Je l'ai fait fonctionner comme ça, j'ai 2 storyboard comme Imre Kelényi l'a dit, l'un avec les mises en page automatiques activées et l'autre sans, puis dans le délégué de l'application, je vérifie simplement quelle version ils utilisent et sélectionnez le bon storyboard:

#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

Avoir 2 cibles fonctionne également mais me semble exagéré

Marchinram
la source
1
Vous avez raison. Cela fonctionne tant que vous chargez des storyboards à partir du code et que vous n'utilisez pas le paramètre "Main Storyboard" de la cible dans Xcode. J'ajoute une référence à votre réponse à partir de mon message.
Imre Kelényi du
SYSTEM_VERSION_GREATER_THAN_OR_EQUAL_TOest exagéré. Testez simplement une classe iOS 6 uniquement contre zéro. Voir developer.apple.com/library/mac/#documentation/developertools/…
mat
ouais bons points, je ne pensais pas vraiment à la restauration quand j'ai répondu initialement
marchinram
Euh, n'utilisez pas willFinishLaunchingWithOptions - J'ai obtenu une "application de terminaison en raison d'une exception non interceptée 'NSInvalidUnarchiveOperationException', raison: 'Impossible d'instancier la classe nommée NSLayoutConstraint'" exécutant le simulateur sous iOS 5.1. Le problème ne se produit pas avec didFinishLaunchingWithOptions.
Elise van Looij
4

Si les différences de disposition ne sont pas importantes, il est beaucoup plus facile d'utiliser des ressorts et des entretoises pour positionner les éléments.

Rich Apodaca
la source
3

Inspiré par l'idée de cible unique de @ marchinram, c'est la solution que j'ai finalement trouvée. Deux storyboards, un pour les jambes de force et les ressorts et un pour la mise en page automatique. Dans le résumé de la cible, j'ai défini le storyboard de mise en page automatique par défaut. Ensuite, dans appDelegate, je vérifie si je dois charger le storyboard à jambes et ressorts pré-6.0 après tout:

    - (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];
    }

En outre, j'ai défini la cible de déploiement du storyboard struts-and-springs sur iOS 5.1 et celle du storyboard de mise en page automatique sur Project SDK (iOS 6.0).

Je voulais vraiment faire le changement avant que la valeur par défaut dans le storyboard ne soit chargée, dans willFinishLaunchingWithOptions: mais cela se traduit par une `` NSInvalidUnarchiveOperationException '', raison: `` Impossible d'instancier la classe nommée NSLayoutConstraint '', peu importe ce que j'ai essayé.

Elise van Looij
la source
0

J'ai trouvé que définir la taille de la vue principale Xib sur Freeform, puis utiliser la taille automatique fonctionne un régal. Pas de soucis dans le code pour un problème de vue.

Anonyme
la source