samedi 10 mars 2012

Conversion iPhone Apps Apps universelle

Eh bien, la NDA a enfin levé, afin que nous puissions commencer à parler de l'iPhone SDK 3.2 et l'iPad. Le lieu de départ logique semble être la façon de convertir vos applications existantes dans un «App universelle" qui fonctionne nativement à la fois sur l'iPad et l'iPhone / iPod touch. Maintenant, beaucoup d'entre vous ont probablement déjà dû trouver ce genre de choses afin que vous pourriez obtenir votre mise à jour le soft le magasin aujourd'hui, mais pour ceux qui n'ont pas emprunter la voie des premiers à adopter, prenons quelques minutes pour examiner le processus . C'est assez simple mais il ya un peu de pièges.
Note: Il ya des choses supplémentaires que vous devez savoir, afin de lire ce post aussi avant de s'attaquer à votre mise à jour.

Cibler tous les périphériques


La première chose que vous avez à faire est d'identifier ce que vous voulez construire votre application existante comme une application universelle. Pour cet article, j'utilise le projet Xcode à partir OpenGL ES application générateur de particules, Mais je vais essayer de garder les informations générales. Remarque: l'étape suivante n'est pas nécessaire si vous utilisez Xcode Target Project Update pour iPad l'option a parlé here.

Apportez votre fenêtre Infos sur le projet dans Xcode soit en double-cliquant sur le noeud racine de votre projet dans le Groupes & Fichiers volet ou en sélectionnant des paramètres du projet Modifier dans le menu Projet, puis naviguez jusqu'à la Build onglet. Maintenant, le changement que nous sommes sur le point de faire doit être fait pour toutes les configurations, alors assurez-vous que les Configuration menu contextuel est réglé Toutes les configurations, Sinon vous allez seulement faire le changement sur une seule configuration.

Nous avons besoin de changer un paramètre appelé Famille périphérique cible, Donc de type Target dans la barre de recherche, ou simplement la recherche pour cette entrée manuellement (ce sera sous la Deployment rubrique). En ce moment, il devrait ressembler à ceci:

Screen shot 2010-04-01 at 10.09.58 AM.png


Voyez comment il est dit iPhone? Ouais, tu sais quoi faire. Cliquez dessus et le modifier de sorte qu'il lit iPhone/iPad, Comme ceci:

select_target.png


Bon! maintenant vous êtes fait, pas vrai? Très probablement, non.

Audit des Tailles codés en dur


La prochaine chose que vous allez avoir à faire est de l'audit de votre application pour voir si vous codés en dur de la taille de l'écran n'importe où dans votre application. Vous ne devriez pas avoir codé ces valeurs, mais avouons-le, nous avons tous fait. Une Projet Trouver (F) pour 320 and 480 et qui devrait tourner l'un quelconque de ces valeurs codées en dur. Dans le code de générateur de particules, je l'ai fait dans un seul endroit, dans le code qui crée un UIImage de la vue OpenGL. La ligne de code où je l'ai fait ressemble à ceci:
    CGImageRef imageRef = CGImageCreate(320, 480, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

Habituellement, le correctif de ce sera évident. Au lieu de coder en dur, vous voulez tirer la largeur et la hauteur de la vue OpenGL. Le code où je l'ai fait existe réellement dans la classe GLView, donc je peux le réparer comme ceci:
    CGImageRef imageRef = CGImageCreate(self.frame.size.width, self.frame.size.height, bitsPerComponent, bitsPerPixel, bytesPerRow, colorSpaceRef, bitmapInfo, provider, NULL, NO, renderingIntent);

Mais, si ce que vous avez codé en dur est la taille réelle de la vue? Alors vous avez besoin pour tirer la taille de l'écran principal lieu de la vue. C'est assez facile à faire.
    UIScreen *screen = [UIScreen mainScreen];
[myView setFrame:[screen applicationFrame]];


Traiter avec des tailles de fenêtres différents


Très probablement celui de votre application instance de UIWindow est contenue dans votre MainWindow.xib fichier qui est chargé automatiquement. Très probablement, cette fenêtre est codé en dur pour 320x480. Maintenant, vous pourriez penser que vous pouvez juste aller dans Interface Builder et de définir les attributs autosize pour la fenêtre et il obtiendra redimensionnée pour vous au moment du lancement. Vous auriez tort. Il n'ya pas de vérification automatique pour s'assurer que votre fenêtre est la bonne taille.

Vous devez vous assurer que la fenêtre est la bonne taille pour le périphérique que vous utilisez sur. Il ya essentiellement deux façons de le faire. Si votre demande est telle que vous avez juste besoin de redimensionner la fenêtre et les attributs de votre autosize se chargeront de faire tout ce que l'air agréable, alors vous pouvez simplement gérer ce programme dans applicationDidFinishLaunching: par réglage de la taille de la fenêtre à la taille de l'écran, moins de la barre d'état Andy tous les autres objets contrôlés par l'iPhone OS (ce qui est connu comme le Cadre de l'application). Faire cela ressemble presque exactement à la mise de la taille de la vue ci-dessus:
    CGRect  rect = [[UIScreen mainScreen] bounds];
[window setFrame:rect];

Maintenant, c'est effectivement une bonne approche pour la Particles demande parce qu'elle a un affichage plein écran. Cependant, l'iPad et l'iPhone sont des dispositifs très différents, et il ya plusieurs composants UI disponible sur l'iPad qui ne sont pas disponibles (du moins pas encore) sur l'iPhone, tels que les vues et les vues diviser pop up. Pour de nombreuses applications, des applications particulièrement complexes en utilisant un grand nombre de points de vue UIKit et contrôles, vous allez probablement vouloir fournir le fichier NIB complètement différent basé sur le périphérique sur lequel le code s'exécute.

Spécifique au périphérique Info.plist Entrées


Le fichier une pointe très importante dans toutes les applications iPhone est, bien sûr, MainWindow.xib, Et il doit y avoir une façon de dire à votre application pour utiliser un autre MainWindow.xib pour les différents périphériques. En fait, il est. Pour chaque clé qui Info.plist supports, tels NSMainNibFile, qui est utilisé pour spécifier le nom du fichier de l'application nib principal, vous pouvez désormais spécifier les entrées spécifiques à l'appareil. Si vous fournissez un dispositif spécifique d'entrée pour le périphérique de l'application est actuellement en cours sur, il va utiliser le périphérique valeur spécifique, sinon il va simplement utiliser la valeur normale.

Spécifiques à l'appareil les touches sont exactement les mêmes que la clé d'origine ou de défaut, sauf le nom de clé est suivi par un tilde (~) et ensuite le nom de l'appareil dans tous les-lettres minuscules. Alors, pour dire à nos applications pour charger un fichier nib différentes pour l'iPad, on peut ajouter une touche appelée NSMainNibFile ~ ipad et puis spécifiez le nom du fichier nib à utiliser lors du lancement sur un iPad. Pour les iPhone et iPod touch, il continuera à utiliser la valeur par défaut, MainWindow.xib, Mais pour l'iPad, il va utiliser le fichier nib que vous avez spécifié dans le nouveau dispositif-clé spécifique.

Vous pouvez ajouter une nouvelle version de MainWindow.xib à votre projet en sélectionnant le Resources groupe et en choisissant Ajouter un nouveau fichier dans le menu Fichier. De l'assistant Nouveau fichier, sélectionnez Interface utilisateur sous l'iPhone OS, puis sélectionnez Demande XIB, Et assurez-vous de sélectionner le bon périphérique dans le Product drop-down.

Screen shot 2010-04-01 at 10.43.29 AM.png


Assurez-vous que vous n'oubliez pas de connecter tous les points de vente et les actions dans ce nib nouveau les mêmes magasins et les actions que vous avez utilisé dans la plume d'autres. Rappelez-vous, un seul des plumes application sera chargée, donc il n'y a pas de conflit.

Pour toute clé dans la Info.plist fichier, vous pouvez utiliser cette même technique pour remplacer la valeur par défaut avec un dispositif de particuliers. Vous pourriez, par exemple, ont le démarrage version iPhone dans le Portrait et le début la version iPad en mode paysage, comme ceci:
    ...
<key>UIInterfaceOrientationkey>
<string>UIInterfaceOrientationPortraitstring>
<key>UIInterfaceOrientation~ipadkey>
<string>UIInterfaceOrientationLandscapeLeftstring>
...

Programmation dispositif de détermination


Si vous avez du code qui a besoin de varier selon qu'il fonctionne sur l'iPad ou l'iPhone / iPod touch, Apple a fourni une nouvelle macro appelée UI_USER_INTERFACE_IDIOM () qui va vous le dire. Il existe actuellement deux valeurs définies, et UIUserInterfaceIdiomPhone UIUserInterfaceIdiomPad, et cette macro retourne la valeur qui correspond à l'appareil étant exécuté. Ainsi, par exemple, si vous aviez besoin de pousser un contrôleur de vue sur la pile de navigation, mais il voulait une plume différente utilisée pour l'iPad que l'iPhone, vous pourriez faire ceci:
    MyController *controller = nil;

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad)
controller = [[MyController alloc] initWithNibName:@"MyiPadNib" bundle:nil];
else
controller = [[MyController alloc] initWithNibName:@"MyiPodNib" bundle:nil];

[self.navigationController pushViewController:controller animated:YES];
[controller release];

Si vous avez besoin plus fine-grain de contrôle, et ont besoin de savoir exactement quel appareil, il n'y a aucun fonctionnaire, ainsi pris en charge pour déterminer le périphérique exacte. La grande majorité du temps, vous vous pensez avoir besoin de connaître l'appareil, vous n'avez pas réellement besoin de connaître le périphérique, vous avez juste besoin de savoir quelles fonctionnalités sont prises en charge. Même si vous pouvez trouver le code sur le web qui va déterminer le dispositif basé sur UIDevice, vous ne devriez vraiment pas votre logique de base sur ce point car un tel code peut être fragile car vous ne savez pas ce que les futurs appareils existeront, ou ce qu'ils caractéristiques aura.

Dans des cas comme le sélecteur d'image, Apple fournit un moyen de déterminer quelles fonctionnalités sont disponibles sur votre appareil, comme s'il ya une caméra, et si cette caméra prend en charge la vidéo. Quand Apple a pas un contrôle spécifique ou d'essais, ce que vous pouvez faire est d'utiliser NSClassFromString (), qui (comme c'est probablement évident à partir du nom) crée une instance de classe basée sur le nom d'une classe contenue dans une chaîne. Si cela renvoie nil, alors vous savez la classe que vous vous posez à propos ne sont pas disponibles. Vous pouvez envelopper votre code qui utilise des classes qui ne sont pas disponibles partout dans ces contrôles et de faire du code qui fonctionne correctement sur tous les appareils, et continuera de le faire à l'avenir (pour la plupart - il n'est jamais possible de 100% d'avenir la preuve de code). Voici un exemple de vérification de l'existence de l'UISplitViewController, qui est une nouvelle classe uniquement disponible sur l'iPad:
    Class splitViewController = NSClassFromString(@"UISplitViewController");
if (splitViewController)
{
UISplitViewController* mySplitViewController = [[splitVCClass alloc] init];
// ... configure, use, then release
}

Vous pouvez faire la même chose avec des fonctions C en vérifiant si la fonction est NULL, par exemple, l'un des cadres ajoutée avec l'iPhone SDK 3.2 est CoreText.framework. Si nous voulions utiliser le CTFontCreateWithName function () pour créer une nouvelle police à l'aide de ce cadre, nous avons pu envelopper la logique dans un idiome vérifier l'interface, comme ci-dessus, ou nous pourrions juste vérifier pour voir si la fonction que nous voulons utiliser existe en voyant si le symbole est CTFontCreateWithName NULL lors de l'exécution, comme ceci:
    if (CTFontCreateWithName != NULL)
CTFontFontRef myFont = CTFontCreateWithName(@"Comic Sans", 14.0, NULL);


Allez, allez, iPad Gadget, Go!


Eh bien, cela couvre à peu près les bases, vous aurez besoin de convertir vos applications iPhone Apps existantes pour Universal. Le plus complexe de votre application, plus vous aurez envie d'envisager de faire iPad séparés et les applications iPhone. Je vais vous montrer comment ajouter une autre cible de votre projet Xcode vous pouvez donc générer deux applications du même projet dans un futur post. Pour de nombreuses applications, cependant, cela devrait être suffisant pour vous permettre le portage de suite, donc le port de suite!

Aucun commentaire: