entlassenModalViewControllerAnimated veraltet


103

Ich habe gerade ein Upgrade auf XCode 4.5 durchgeführt, um meine iOS-App so zu aktualisieren, dass sie auf dem 4-Zoll-Display für das iPhone 5 ausgeführt werden kann. In dismissModalViewControllerAnimated:' is deprecatedder Zeile wird jedoch ein Build-Fehler angezeigt :

[self dismissModalViewControllerAnimated:NO];

Ich habe versucht, mit einem Completion-Handler (aber auf NULL gesetzt) ​​wie folgt auf die empfohlene Überladung zu aktualisieren:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Aber dann wirft diese Zeile zwei Fehler:

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

Vielen Dank!

Antworten:


307

Die neue Methode ist:

[self dismissViewControllerAnimated:NO completion:nil];

Das Wort modal wurde entfernt; Wie beim vorgestellten API-Aufruf:

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

Die Gründe wurden in der WWDC-Sitzung 236 2012 - Die Entwicklung von View Controllern auf iOS- Videos erörtert . Im Wesentlichen sind die von dieser API präsentierten View-Controller nicht mehr immer modal, und da sie einen Completion-Handler hinzugefügt haben, war es ein guter Zeitpunkt, ihn umzubenennen.

Als Antwort auf den Kommentar von Marc:

Was ist der beste Weg, um alle Geräte 4.3 und höher zu unterstützen? Die neue Methode funktioniert in iOS4 nicht, die alte Methode ist in iOS6 jedoch veraltet.

Mir ist klar, dass dies fast eine separate Frage ist, aber ich denke, es ist eine Erwähnung wert, da nicht jeder das Geld hat, alle seine Geräte alle 3 Jahre zu aktualisieren, so dass viele von uns einige ältere Geräte (vor 5.0) haben. So sehr es mich auch schmerzt, es zu sagen, müssen Sie sich überlegen, ob es sich lohnt, unter 5,0 zu zielen. Es gibt viele neue und coole APIs, die unter 5.0 nicht verfügbar sind. Und Apple macht es immer schwieriger, sie ins Visier zu nehmen. Die Unterstützung von armv6 wird beispielsweise von Xcode 4.5 gestrichen.

Um unter 5.0 zu zielen (solange der Abschlussblock Null ist), verwenden Sie einfach die handliche respondsToSelector: Methode.

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

Als Antwort auf einen weiteren Kommentar von Marc:

Das könnte eine Menge If-Anweisungen in meiner Anwendung sein! ... Ich habe darüber nachgedacht, eine Kategorie zu erstellen, die diesen Code kapselt. Würde das Erstellen einer Kategorie in UIViewControler mich ablehnen?

und einer von Full Decent:

... gibt es eine Möglichkeit, manuell zu veranlassen, dass keine Compiler-Warnung angezeigt wird?

Erstens, nein, UIViewControllerwenn Sie eine Kategorie an und für sich erstellen, wird Ihre App nicht abgelehnt. es sei denn, diese Kategoriemethode wird als private APIs oder ähnliches bezeichnet.

Eine Kategoriemethode ist ein außerordentlich guter Ort für solchen Code. Da die veraltete API nur einmal aufgerufen wird, gibt es nur eine Compiler-Warnung.

Um den Kommentar (Frage) von Full Decent zu beantworten, können Sie Compiler-Warnungen manuell unterdrücken. Hier ist ein Link zu einer Antwort auf SO zu diesem Thema . Eine Kategoriemethode ist auch ein großartiger Ort, um eine Compiler-Warnung zu unterdrücken, da Sie die Warnung nur an einer Stelle unterdrücken. Sie möchten den Compiler sicher nicht umsonst zum Schweigen bringen.

Wenn ich eine einfache Kategoriemethode dafür schreiben würde, könnte es ungefähr so ​​aussehen:

@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
Was ist der beste Weg, um alle Geräte 4.3 und höher zu unterstützen? Die neue Methode funktioniert in iOS4 nicht, die alte Methode ist in iOS6 jedoch veraltet. Rock und ein harter Ort?
Marc

@Marc Ich habe meiner Antwort hinzugefügt, um Ihr Anliegen anzusprechen.
NJones

Vielen Dank. Das könnten ziemlich viele If-Aussagen in meiner Bewerbung sein! Ich denke, der gleiche Ansatz könnte funktionieren, wenn die Eigenschaft 'modalViewController' verwendet wird. Ich habe darüber nachgedacht, eine Kategorie zu erstellen, die diesen Code enthält. Würde das Erstellen einer Kategorie in UIViewControler mich ablehnen?
Marc

Gibt if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }es für den Code eine Möglichkeit, manuell zu veranlassen, dass keine Compiler-Warnung angezeigt wird?
William Entriken

@FullDecent Ja, das kannst du. Ich habe meine Antwort mit einigen Informationen dazu bearbeitet.
NJones

6

In iOS 6 und höher können Sie Folgendes verwenden:

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

Anstatt:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... und Sie können verwenden:

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

Anstatt

[self presentModalViewController:picker animated:YES];    

4

[self dismissModalViewControllerAnimated:NO]; wurde veraltet.

Verwenden Sie [self dismissViewControllerAnimated:NO completion:nil];stattdessen.


4

Verwenden

[self dismissViewControllerAnimated:NO completion:nil];

3

Die Warnung ist immer noch da. Um es loszuwerden, habe ich es in einen Selektor wie diesen gestellt:

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

Es kommt Menschen mit Zwangsstörungen wie mir zugute;)


Sie sollten die if-Anweisung wechseln, da ich glaube, dass eine veraltete Methode nicht dazu führt respondsToSelector, dass false zurückgegeben wird. Daher wird das neue dismissViewControllerAnimated:System erst nach einem zukünftigen Update aufgerufen, bei dem es möglicherweise dismissModalViewControllerAnimated:vollständig entfernt wird.
Jsdodgers

0

Hier ist die entsprechende presentViewController-Version, die ich verwendet habe, wenn sie anderen Neulingen wie mir hilft:

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

Ich hatte einen ViewController "generisch" verwendet und konnte die modale Ansicht so einstellen, dass sie je nach Aufruf unterschiedlich aussah (mit setHidden und setImage). und die Dinge haben vorher gut funktioniert, aber performSelector ignoriert 'Set'-Sachen, so dass es am Ende eine schlechte Lösung zu sein scheint, wenn Sie versuchen, effizient zu sein, wie ich es versucht habe ...

Durch die Nutzung unserer Website bestätigen Sie, dass Sie unsere Cookie-Richtlinie und Datenschutzrichtlinie gelesen und verstanden haben.
Licensed under cc by-sa 3.0 with attribution required.