licenciementModalViewControllerAnimated obsolète

103

Je viens de passer à XCode 4.5 pour mettre à jour mon application iOS afin qu'elle s'exécute sur l'écran 4 pouces de l'iPhone 5, mais j'obtiens une erreur de construction disant dismissModalViewControllerAnimated:' is deprecatedsur 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 alors cette ligne jette deux erreurs:

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

Merci!

Mick Byrne
la source

Réponses:

307

La nouvelle méthode est:

[self dismissViewControllerAnimated:NO completion:nil];

Le mot modal a été supprimé; Comme pour l'appel API de présentation:

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

Les raisons ont été discutées dans la session 236 de la WWDC 2012 - L'évolution des contrôleurs de vue sur la vidéo iOS . Essentiellement, les contrôleurs de vue présentés par cette API ne sont plus toujours modaux, et comme ils ajoutaient un gestionnaire de complétion, c'était le bon moment pour 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 que c'est presque une question distincte, mais je pense que cela vaut la peine d'être mentionné car tout le monde n'a pas l'argent pour mettre à niveau tous ses appareils tous les 3 ans, donc beaucoup d'entre nous ont des appareils plus anciens (pré 5.0). Pourtant, même si cela me fait mal de le dire, vous devez vous demander s'il vaut la peine de cibler en dessous de 5,0. Il existe de nombreuses API nouvelles et intéressantes non disponibles sous la version 5.0. Et Apple rend continuellement plus difficile de les cibler; Le support 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 respondsToSelectorméthode handy:.

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 être beaucoup d'instructions If dans mon application! ... Je pensais créer une catégorie qui encapsulerait ce code, la création d'une catégorie sur UIViewControler me ferait-elle rejeter?

et un de Full Decent:

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

Premièrement, non, créer une catégorie UIViewControlleren soi n'entraînera pas le rejet de votre application; à moins que cette méthode de catégorie ne s'appelle API privées ou quelque chose de similaire.

Une méthode de 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 (question) de Full Decent, oui, vous pouvez supprimer manuellement les avertissements du compilateur. Voici un lien vers une réponse sur SO sur ce même sujet . Une méthode de catégorie est également un excellent endroit pour supprimer un avertissement du compilateur, car vous ne supprimez l'avertissement qu'à un seul 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 être quelque chose comme 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
NJones
la source
2
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. Rock et un endroit dur?
Marc
@Marc J'ai ajouté à ma réponse pour répondre à votre inquiétude.
NJones
Merci. Cela pourrait être beaucoup de déclarations If dans mon application! Je suppose que la même approche pourrait fonctionner lors de l'utilisation de la propriété 'modalViewController'. Je pensais créer une catégorie qui encapsulerait ce code, la création d'une catégorie sur UIViewControler me ferait-elle rejeter?
Marc
Pour le code, if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }existe-t-il un moyen de faire en sorte que cela ne présente pas d'avertissement du compilateur?
William Entriken
@FullDecent Oui, vous pouvez. J'ai édité ma réponse avec quelques informations à ce sujet.
NJones
6

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];    
Dipang
la source
4

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

Utilisez [self dismissViewControllerAnimated:NO completion:nil];plutôt.

Jayprakash Dubey
la source
4

Utilisation

[self dismissViewControllerAnimated:NO completion:nil];
Mak083
la source
3

L'avertissement est toujours là. Afin de 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];
}

Cela profite aux personnes atteintes de TOC comme moi;)

kjoelbro
la source
Vous devriez changer l'instruction if car je pense qu'une méthode obsolète ne provoquera respondsToSelectorpas le retour de false. Ainsi, le nouveau dismissViewControllerAnimated:ne sera jamais appelé jusqu'à une future mise à jour où ils pourraient éventuellement être dismissModalViewControllerAnimated:complètement supprimés .
Jsdodgers
0

Voici la version correspondante de presentViewController que j'ai utilisée si elle 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 «génériquement» et j'ai pu faire en sorte que la vue modale apparaisse différemment en fonction de ce qu'elle était appelée à faire (en utilisant setHidden et setImage). et les choses fonctionnaient bien avant, mais performSelector ignore les trucs 'set', donc à la fin, cela semble être une mauvaise solution si vous essayez d'être efficace comme j'ai essayé de l'être ...

Walter
la source