dismissModalViewControllerАнімований застарілий


103

Щойно я оновив XCode 4.5, щоб оновити додаток для iOS, щоб він працював на 4-дюймовому дисплеї для iPhone 5, але я отримую помилку в збірці dismissModalViewControllerAnimated:' is deprecated:

[self dismissModalViewControllerAnimated:NO];

Я спробував оновити до рекомендованої перевантаження за допомогою обробника завершення (але встановлено на NULL) таким чином:

[self dismissModalViewControllerAnimated:NO completion:NULL];

Але тоді цей рядок видає дві помилки:

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

Дякую!

Відповіді:


307

Новий метод:

[self dismissViewControllerAnimated:NO completion:nil];

Слово модальне видалено; Як це було для представлення виклику API:

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

Причини були обговорені на сесії 236 WWDC - Еволюція контролерів перегляду на iOS Video. По суті, контролери перегляду, представлені цим API, не завжди є модальними, і оскільки вони додавали обробник завершення, настав час перейменувати його.

У відповідь на коментар Марка:

Який найкращий спосіб підтримувати всі пристрої 4.3 та вище? Новий метод не працює в iOS4, проте старий метод застарілий в iOS6.

Я розумію, що це майже окреме питання, але я думаю, що це варто згадати, оскільки не кожен має гроші на оновлення всіх своїх пристроїв кожні 3 роки, тому багато хто з нас мають старіші (до 5,0) пристрої. І все-таки, наскільки мені боляче це сказати, потрібно врахувати, чи варто орієнтуватися нижче 5,0. Існує багато нових і цікавих API, які не доступні нижче 5,0. І Apple постійно ускладнює націлювання на них; Наприклад, підтримка armv6 випадає з Xcode 4.5.

Для націлювання нижче 5,0 (поки блок заповнення дорівнює нулю) просто скористайтеся зручним respondsToSelectorметодом:

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

У відповідь на ще один коментар Марка:

Це може бути дуже багато, якби висловлювання у моїй програмі! ... Я думав створити категорію, яка інкапсулювала цей код, чи створила б категорію на UIViewControler, щоб мене відхилили?

і один з Full Decent:

... чи є спосіб вручну спричинити це, щоб не подати попередження компілятора?

По-перше, ні, створення категорії само по UIViewControllerсобі не призведе до відхилення вашої програми; якщо цей метод категорії не називається приватними API чи чимось подібним.

Метод категорії є надзвичайно хорошим місцем для такого коду. Крім того, оскільки був би один виклик застарілого API, було б лише одне попередження компілятора.

Щоб вирішити коментар (питання) Full Decent, так, ви можете придушити попередження компілятора вручну. Ось посилання на відповідь на ТА на цю саму тему . Метод категорії також є прекрасним місцем для придушення попередження компілятора, оскільки ви придушуєте попередження лише в одному місці. Ви, звичайно, не хочете обійтись, замовчуючи компілятор вольно-невільно.

Якби я писав простий метод категорії для цього, це може бути щось подібне:

@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
Який найкращий спосіб підтримувати всі пристрої 4.3 та вище? Новий метод не працює в iOS4, проте старий метод застарілий в iOS6. Рок і важке місце?
Марк

@Marc Я додав у свою відповідь, щоб вирішити вашу проблему.
NJones

Дякую. Це може бути досить багато тверджень If у моїй заяві! Я думаю, той самий підхід міг би працювати при використанні властивості 'modalViewController'. Я думав створити категорію, яка інкапсулювала цей код, чи створила категорію на UIViewControler, щоб мене відхилили?
Марк

Що стосується коду, if ([self respondsToSelector:@selector(presentViewController:animated:completion:)]){ [self presentViewController:test animated:YES completion:nil]; } else { [self presentModalViewController:test animated:YES]; }чи існує спосіб вручну викликати, щоб не було попередження компілятора?
Вільям Ентрікен

@FullDecent Так, можна. Я відредагував свою відповідь із деякою інформацією про це.
NJones

6

Тепер в iOS 6 і вище ви можете використовувати:

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

Замість:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

... І ви можете використовувати:

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

Замість

[self presentModalViewController:picker animated:YES];    

4

[self dismissModalViewControllerAnimated:NO]; застаріло.

Використовуйте [self dismissViewControllerAnimated:NO completion:nil];замість цього.


4

Використовуйте

[self dismissViewControllerAnimated:NO completion:nil];

3

Попередження все ще є. Для того, щоб позбутися від нього, я помістив його в селектор так:

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

Це приносить користь людям з OCD, як я;)


Ви повинні переключити оператор if, оскільки я вважаю, що застарілий метод не призведе respondsToSelectorдо повернення false. Таким чином, нове dismissViewControllerAnimated:не буде називатися до наступного оновлення, яке, можливо, може видалитись dismissModalViewControllerAnimated:взагалі.
Jsdodgers

0

Ось відповідна версія presentViewController, яку я використовував, якщо вона допомагає іншим новачкам, як я:

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

Я використовував ViewController 'генерично' і міг змусити модальний вигляд відображатися по-різному в залежності від того, що йому було викликано (використовуючи setHidden та setImage). і раніше добре працювали, але PerformSelector ігнорує "встановлені" речі, тож, врешті-решт, це здається поганим рішенням, якщо ви намагаєтесь бути ефективними, як я намагався бути ...

Використовуючи наш веб-сайт, ви визнаєте, що прочитали та зрозуміли наші Політику щодо файлів cookie та Політику конфіденційності.
Licensed under cc by-sa 3.0 with attribution required.