dismissModalViewControllerAnimated deprecated


Я только что обновился до 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')

спасибо!

6 99

6 ответов:

новый метод:

[self dismissViewControllerAnimated:NO completion:nil];

слово модальные был удален; как это было для представления вызова API:

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

причины были обсуждены в 2012 WWDC сессия 236-эволюция контроллеров вида на iOS видео. По сути, контроллеры представления, представленные этим 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 получить мне отказано?

и один из полных приличных:

...Есть ли способ вручную заставить это не представлять предупреждение компилятора?

во-первых, нет, создание категории на UIViewController само по себе не будет отклонено ваше приложение; если только этот метод категории не называется private APIs или что-то подобное.

метод категорию это очень хорошее место для такого кода. Кроме того, поскольку будет только один вызов устаревшего API, будет только одно предупреждение компилятора.

чтобы обратиться к комментарию(вопросу) Full Decent, да, вы можете подавить предупреждения компилятора вручную. вот ссылка на ответ на так на эту самую тему. Метод category также является отличным местом для подавления предупреждения компилятора, так как вы подавляете предупреждение только в одном месте. Вы, конечно, не хотите идти вокруг молчит компилятор волей-неволей.

если бы я написал простой метод категории для этого, это могло бы быть что-то вроде этого:

@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

теперь в iOS 6 и выше, вы можете использовать:

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

вместо:

[[Picker parentViewControl] dismissModalViewControllerAnimated:YES];

...И вы можете использовать:

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

вместо

[self presentModalViewController:picker animated:YES];    

[self dismissModalViewControllerAnimated:NO]; была прекращена.

использовать [self dismissViewControllerAnimated:NO completion:nil]; вместо.

использовать

[self dismissViewControllerAnimated:NO completion:nil];

предупреждение все еще там. Чтобы избавиться от него, я поместил его в селектор следующим образом:

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

это приносит пользу людям с ОКР, как я;)

вот соответствующая версия 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 'generically' и смог заставить модальное представление выглядеть по-разному в зависимости от того, что он должен был делать (используя setHidden и setImage). и раньше все работало хорошо, но performSelector игнорирует "набор" вещей, поэтому в конце концов это кажется плохим решением, если вы пытаетесь быть эффективным, как я пытался быть...