web-dev-qa-db-fra.com

licencierModalViewControllerAnimated obsolète

Je viens de mettre à niveau vers XCode 4.5 pour mettre à jour mon application iOS pour qu'elle s'exécute sur l'écran 4 pouces de l'iPhone 5, mais je reçois une erreur de construction en indiquant dismissModalViewControllerAnimated:' is deprecated sur la ligne:

[self dismissModalViewControllerAnimated:NO];

J'ai essayé de mettre à jour la surcharge recommandée avec un gestionnaire d'achèvement (mais défini sur NULL) comme ceci:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Mais cette ligne génère deux erreurs:

warning: 'TabBarController' may not respond to '-presentModalViewController:animated:completion:'
Instance method '-presentModalViewController:animated:completion:' not found (return type defaults to 'id')

Merci!

100
Mick Byrne

La nouvelle méthode est:

[self dismissViewControllerAnimated:NO completion:nil];

Le modal Word a été supprimé. Comme pour l'appel API présentateur:

[self presentViewController:vc animated:NO completion:nil];

Les raisons ont été discutées dans la (236) Session WWDC 2012 2012 - L'évolution des contrôleurs de vue sur iOS Vidéo. Pour l'essentiel, les contrôleurs de vues présentés par cette API ne sont plus toujours modaux et, comme ils ajoutaient un gestionnaire d'achèvement, il était temps de le renommer.

En réponse au commentaire de Marc:

Quelle est la meilleure façon de prendre en charge tous les appareils 4.3 et supérieurs? La nouvelle méthode ne fonctionne pas dans iOS4, mais l'ancienne méthode est obsolète dans iOS6.

Je me rends compte qu’il s’agit presque d’une question distincte, mais je pense que cela vaut la peine d’être mentionné, car tout le monde n’a pas l’argent nécessaire pour mettre à niveau tous ses appareils tous les 3 ans; Néanmoins, même si cela me fait mal de le dire, vous devez vous demander s'il vaut la peine de cibler au-dessous de 5,0. Il existe de nombreuses nouvelles API intéressantes non disponibles sous la version 5.0. Et Apple ne cesse de rendre plus difficile leur ciblage. Le support d’armv6 est supprimé de Xcode 4.5, par exemple.

Pour cibler en dessous de 5.0 (tant que le bloc d'achèvement est nul), utilisez simplement la méthode pratique respondsToSelector:.

if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
    [self presentViewController:test animated:YES completion:nil];
} else {
    [self presentModalViewController:test animated:YES];
}

En réponse à un autre commentaire de Marc:

Cela pourrait faire beaucoup de déclarations If dans mon application! ... Je pensais créer une catégorie qui encapsulait ce code, est-ce que créer une catégorie sur UIViewControler me ferait rejeter?

et un de Full Decent:

... y a-t-il un moyen de faire en sorte que cela ne présente pas un avertissement du compilateur?

Premièrement, non, créer une catégorie sur UIViewController en soi ne fera pas rejeter votre application; sauf si cette méthode de catégorie appelée API privée ou quelque chose de similaire.

Une méthode par catégorie est un très bon endroit pour un tel code. De plus, comme il n'y aurait qu'un seul appel à l'API obsolète, il n'y aurait qu'un seul avertissement du compilateur.

Pour répondre au commentaire de Full Decent (question), vous pouvez supprimer les avertissements du compilateur manuellement. Voici un lien vers une réponse sur SO à ce sujet même) . Une méthode de catégorie est également un excellent endroit pour supprimer un avertissement du compilateur, car vous ne supprimez que l’avertissement dans un endroit. Vous ne voulez certainement pas faire taire le compilateur bon gré mal gré.

Si je devais écrire une méthode de catégorie simple pour cela, cela pourrait ressembler à ceci:

@implementation UIViewController (NJ_ModalPresentation)
-(void)nj_presentViewController:(UIViewController *)viewControllerToPresent animated:(BOOL)flag completion:(void (^)(void))completion{
    NSAssert(completion == nil, @"You called %@ with a non-nil completion. Don't do that!",NSStringFromSelector(_cmd));
    if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){
        [self presentViewController:viewControllerToPresent animated:flag completion:completion];
    } else {
#pragma clang diagnostic Push
#pragma clang diagnostic ignored "-Wdeprecated-declarations"
        [self presentModalViewController:viewControllerToPresent animated:flag];
#pragma clang diagnostic pop
    }
}
@end
304
NJones

Désormais dans iOS 6 et supérieur, vous pouvez utiliser:

[[Picker presentingViewController] dismissViewControllerAnimated:YES completion:nil];

Au lieu de:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... et vous pouvez utiliser:

[self presentViewController:picker animated:YES completion:nil];

Au lieu de

[self presentModalViewController:picker animated:YES];    
6
Dipang

[self dismissModalViewControllerAnimated:NO]; est obsolète.

Utilisation [self dismissViewControllerAnimated:NO completion:nil]; au lieu.

4
Jayprakash Dubey

Utilisation

[self dismissViewControllerAnimated:NO completion:nil];
4
Mak083

L'avertissement est toujours là. Pour m'en débarrasser, je le mets dans un sélecteur comme celui-ci:

if ([self respondsToSelector:@selector(dismissModalViewControllerAnimated:)]) {
    [self performSelector:@selector(dismissModalViewControllerAnimated:) withObject:[NSNumber numberWithBool:YES]];
} else {
    [self dismissViewControllerAnimated:YES completion:nil];
}

Il profite aux personnes avec OCD comme moi;)

3
kjoelbro

Voici la version correspondante de presentViewController que j'ai utilisée si cela aide d'autres débutants comme moi:

if ([self respondsToSelector:@selector(presentModalViewController:animated:)]) {
    [self performSelector:@selector(presentModalViewController:animated:) withObject:testView afterDelay:0];
} else {
    [self presentViewController:configView animated:YES completion:nil];
}
[testView.testFrame setImage:info]; //this doesn't work for performSelector
[testView.testText setHidden:YES];

J'avais utilisé un ViewController de manière "générique" et pouvais faire en sorte que la vue modale apparaisse différemment en fonction de la raison pour laquelle elle était appelée (en utilisant setHidden et setImage). et les choses fonctionnaient bien auparavant, mais performSelector ignore les trucs 'set', donc à la fin, ça semble être une mauvaise solution si vous essayez d'être aussi efficace que moi….

0
Walter