dismissModalViewControllerAnimated deprecato


103

Ho appena eseguito l'aggiornamento a XCode 4.5 per aggiornare la mia app iOS in modo che funzioni sul display da 4 pollici per iPhone 5, ma ricevo un errore di compilazione che dice dismissModalViewControllerAnimated:' is deprecated:

[self dismissModalViewControllerAnimated:NO];

Ho provato ad aggiornare all'overload consigliato con un gestore di completamento (ma impostato su NULL) come questo:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Ma poi questa riga genera due errori:

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

Grazie!

Risposte:


307

Il nuovo metodo è:

[self dismissViewControllerAnimated:NO completion:nil];

La parola modale è stata rimossa; Come è stato per la chiamata API di presentazione:

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

I motivi sono stati discussi nella sessione 236 del WWDC del 2012 - L'evoluzione dei controller di visualizzazione su video iOS . In sostanza, i controller di visualizzazione presentati da questa API non sono più sempre modali e poiché stavano aggiungendo un gestore di completamento, era un buon momento per rinominarlo.

In risposta al commento di Marc:

Qual è il modo migliore per supportare tutti i dispositivi 4.3 e versioni successive? Il nuovo metodo non funziona in iOS4, ma il vecchio metodo è deprecato in iOS6.

Mi rendo conto che questa è quasi una domanda a parte, ma penso che valga la pena menzionarla poiché non tutti hanno i soldi per aggiornare tutti i loro dispositivi ogni 3 anni, quindi molti di noi hanno dispositivi più vecchi (pre 5.0). Tuttavia, per quanto mi addolori dirlo, devi considerare se vale la pena puntare al di sotto di 5.0. Ci sono molte API nuove e interessanti non disponibili sotto 5.0. E Apple rende continuamente più difficile prenderli di mira; Il supporto di armv6 viene eliminato da Xcode 4.5, ad esempio.

Per puntare al di sotto di 5.0 (fintanto che il blocco di completamento è nullo) basta usare il respondsToSelectormetodo pratico :.

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

In risposta a un altro commento di Marc:

Potrebbero essere molte istruzioni If nella mia applicazione! ... Stavo pensando di creare una categoria che incapsulasse questo codice, la creazione di una categoria su UIViewControler mi avrebbe fatto rifiutare?

e uno da Full Decent:

... c'è un modo per far sì che manualmente non presenti un avviso del compilatore?

In primo luogo, no, la creazione di una categoria UIViewControllerin sé e per sé non farà rifiutare la tua app; a meno che quel metodo di categoria non chiami API private o qualcosa di simile.

Un metodo di categoria è un ottimo posto per tale codice. Inoltre, poiché ci sarebbe solo una chiamata all'API deprecata, ci sarebbe solo un avviso del compilatore.

Per rispondere al commento (domanda) di Full Decent, sì, puoi sopprimere manualmente gli avvisi del compilatore. Ecco un collegamento a una risposta su SO su questo argomento . Un metodo di categoria è anche un ottimo posto per sopprimere un avviso del compilatore, poiché stai sopprimendo l'avviso solo in un punto. Certamente non vuoi andare in giro a silenziare il compilatore, volenti o nolenti.

Se dovessi scrivere un semplice metodo di categoria per questo potrebbe essere qualcosa del genere:

@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

2
Qual è il modo migliore per supportare tutti i dispositivi 4.3 e versioni successive? Il nuovo metodo non funziona in iOS4, ma il vecchio metodo è deprecato in iOS6. Rock e un luogo difficile?
Marc

@ Marc ho aggiunto alla mia risposta per rispondere alla tua preoccupazione.
NJones

Grazie. Potrebbe trattarsi di molte istruzioni If nella mia applicazione! Immagino che lo stesso approccio potrebbe funzionare quando si utilizza la proprietà "modalViewController". Stavo pensando di creare una categoria che incapsulasse questo codice, la creazione di una categoria su UIViewControler mi avrebbe rifiutato?
Marc

Per il codice if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }esiste un modo per far sì che non presenti un avviso del compilatore?
William Entriken

@FullDecent Sì, puoi. Ho modificato la mia risposta con alcune informazioni su questo.
NJones

6

Ora in iOS 6 e versioni successive, puoi utilizzare:

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

Invece di:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... E puoi usare:

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

Invece di

[self presentModalViewController:picker animated:YES];    

4

[self dismissModalViewControllerAnimated:NO]; è stato deprecato.

Usa [self dismissViewControllerAnimated:NO completion:nil];invece.


4

Uso

[self dismissViewControllerAnimated:NO completion:nil];

3

L'avvertimento è ancora lì. Per eliminarlo lo metto in un selettore come questo:

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

Beneficia le persone con disturbo ossessivo compulsivo come me;)


Dovresti cambiare l'istruzione if perché credo che un metodo deprecato non causerà la respondsToSelectorrestituzione di false. Pertanto, il nuovo dismissViewControllerAnimated:non verrà mai chiamato fino a un futuro aggiornamento in cui potrebbero essere rimossi del dismissModalViewControllerAnimated:tutto.
Jsdodgers

0

Ecco la versione di presentViewController corrispondente che ho usato se aiuta altri neofiti come me:

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

Avevo usato un ViewController "genericamente" ed ero in grado di far apparire la vista modale in modo diverso a seconda di ciò che era stato chiamato a fare (usando setHidden e setImage). e le cose funzionavano bene prima, ma performSelector ignora le cose 'set', quindi alla fine sembra essere una soluzione scadente se cerchi di essere efficiente come ho cercato di essere ...

Utilizzando il nostro sito, riconosci di aver letto e compreso le nostre Informativa sui cookie e Informativa sulla privacy.
Licensed under cc by-sa 3.0 with attribution required.