iPhone viewWillAppear не стреляет
96093 просмотра
25 ответа
Я читал многочисленные сообщения о людях , имеющих проблемы с , viewWillAppear
когда вы не создаете иерархию вида только право. Моя проблема в том, что я не могу понять, что это значит.
Если я создам RootViewController
и вызову addSubView
этот контроллер, я ожидаю, что добавленные представления будут подключены к viewWillAppear
событиям.
У кого-нибудь есть пример сложной программной иерархии представлений, которая успешно принимает viewWillAppear
события на каждом уровне?
Документы Apple заявляют:
Предупреждение: Если представление, принадлежащее контроллеру представления, добавляется непосредственно в иерархию представления, контроллер представления не получит это сообщение. Если вы вставляете или добавляете представление в иерархию представлений, и у него есть контроллер представлений, вам следует отправить это сообщение соответствующему контроллеру представлений напрямую. Если это сообщение не будет отправлено контроллеру представления, будет невозможно отобразить любую связанную анимацию.
Проблема в том, что они не описывают, как это сделать. Что значит «напрямую»? Как вы «косвенно» добавляете представление?
Я довольно новичок в Какао и iPhone, так что было бы неплохо, если бы были полезные примеры от Apple, помимо простой хрени Hello World.
Автор: chzk Источник Размещён: 14.06.2019 04:57Ответы (25)
53 плюса
Если вы используете контроллер навигации и задаете его делегат, то методы view {Will, Did} {Appear, Disappear} не запускаются.
Вместо этого вам нужно использовать методы делегирования контроллера навигации:
navigationController:willShowViewController:animated:
navigationController:didShowViewController:animated:
Автор: mmalc
Размещён: 17.10.2008 04:35
29 плюса
Я столкнулся с этой же проблемой. Просто отправьте viewWillAppear
сообщение на ваш контроллер представления, прежде чем добавить его в качестве подпредставления. (Существует один параметр BOOL, который сообщает контроллеру представления, должен ли он быть анимированным, чтобы появиться или нет.)
[myViewController viewWillAppear:NO];
Посмотрите на RootViewController.m в примере Metronome.
(Я на самом деле нашел примеры проектов Apple великолепными. Существует намного больше, чем HelloWorld;)
Автор: lajos Размещён: 28.09.2008 01:2018 плюса
Я наконец нашел решение для этого, что работает!
UINavigationControllerDelegate
Я думаю, что суть этого в том, чтобы установить делегата вашего элемента управления навигацией на viewcontroller, в котором он находится, и реализовать, UINavigationControllerDelegate
и это два метода. Brilliant! Я так взволнован, я наконец нашел решение!
8 плюса
У меня просто была такая же проблема. В моем приложении у меня есть 2 контроллера навигации и нажатие на один и тот же контроллер представления в каждом из них работал в одном случае, а не в другом. Я имею в виду , что при нажатии на тот же контроллер представления в первом UINavigationController
, viewWillAppear
был вызван , но не тогда , когда нажат второй навигации контроллера.
Тогда я наткнулся на этот пост UINavigationController должен вызывать методы viewWillAppear / viewWillDisappear
И понял, что мой второй контроллер навигации действительно переопределил viewWillAppear
. Скрининг кода показал, что я не звонил
[super viewWillAppear:animated];
Я добавил это, и это сработало!
В документации сказано:
Автор: Antoine Размещён: 13.01.2010 02:46Если вы переопределите этот метод, вы должны вызвать super в какой-то момент вашей реализации.
5 плюса
Я использовал навигационный контроллер. Когда я хочу перейти на другой уровень данных или показать свой пользовательский вид, я использую следующее:
[self.navigationController pushViewController:<view> animated:<BOOL>];
Когда я делаю это, у меня viewWillAppear
срабатывает функция. Я предполагаю, что это квалифицируется как «косвенный», потому что я не вызываю сам addSubView
метод. Я не знаю, применимо ли это на 100% к вашему приложению, так как я не могу сказать, используете ли вы навигационный контроллер, но, возможно, это даст подсказку.
4 плюса
Во-первых, панель вкладок должна быть на корневом уровне, то есть добавлена в окно, как указано в документации Apple. Это ключ к правильному поведению.
Во-вторых, вы можете использовать UITabBarDelegate
/ UINavigationBarDelegate
для пересылки уведомлений вручную, но я обнаружил, что для правильной работы всей иерархии вызовов представлений мне нужно было только вручную
[tabBarController viewWillAppear:NO];
[tabBarController viewDidAppear:NO];
а также
[navBarController viewWillAppear:NO];
[navBarController viewDidAppear:NO];
.. только ОДИН РАЗ перед установкой контроллеров представления на соответствующем контроллере (сразу после распределения). С тех пор он корректно вызывал эти методы на своих дочерних контроллерах представления.
Моя иерархия такая:
window
UITabBarController (subclass of)
UIViewController (subclass of) // <-- manually calls [navController viewWill/DidAppear
UINavigationController (subclass of)
UIViewController (subclass of) // <-- still receives viewWill/Did..etc all the way down from a tab switch at the top of the chain without needing to use ANY delegate methods
Простой вызов упомянутых методов на контроллере tab / nav в первый раз гарантировал, что ВСЕ события были перенаправлены правильно. Это остановило меня от необходимости вызывать их вручную из методов UINavigationBarDelegate
/ UITabBarControllerDelegate
.
Sidenote: Любопытно, что когда это не сработало, частный метод
- (void)transitionFromViewController:(UIViewController*)aFromViewController toViewController:(UIViewController*)aToViewController
.. который вы можете видеть из callstack в работающей реализации, обычно вызывает viewWill/Did..
методы, но не делал, пока я не выполнил вышеупомянутое (даже если он был вызван).
Я думаю, что ОЧЕНЬ важно, чтобы UITabBarController
это было на уровне окна, и документы, кажется, подтверждают это.
Надеюсь, что было ясно (иш), с удовольствием отвечу на дальнейшие вопросы.
Автор: Sam Размещён: 26.07.2011 05:103 плюса
Поскольку никакого ответа не принято, и люди (как и я) приземляются здесь, я даю свой вариант. Хотя я не уверен, что это была первоначальная проблема. Когда контроллер навигации добавляется как подпредставление к другому представлению, вы должны сами вызывать методы viewWillAppear / Dissappear и т. Д., Например, так:
- (void) viewWillAppear:(BOOL)animated
{
[super viewWillAppear:animated];
[subNavCntlr viewWillAppear:animated];
}
- (void) viewWillDisappear:(BOOL)animated
{
[super viewWillDisappear:animated];
[subNavCntlr viewWillDisappear:animated];
}
Просто чтобы завершить пример. Этот код появляется в моем ViewController, где я создал и добавил навигационный контроллер в представление, которое я поместил в представление.
- (void)viewDidLoad {
// This is the root View Controller
rootTable *rootTableController = [[rootTable alloc]
initWithStyle:UITableViewStyleGrouped];
subNavCntlr = [[UINavigationController alloc]
initWithRootViewController:rootTableController];
[rootTableController release];
subNavCntlr.view.frame = subNavContainer.bounds;
[subNavContainer addSubview:subNavCntlr.view];
[super viewDidLoad];
}
.h выглядит так
@interface navTestViewController : UIViewController <UINavigationControllerDelegate> {
IBOutlet UIView *subNavContainer;
UINavigationController *subNavCntlr;
}
@end
В nib-файле у меня есть вид, а под этим видом у меня есть метка изображения и контейнер (другой вид), куда я помещаю контроллер. Вот как это выглядит. Я должен был кое-что исправить, так как это было работой для клиента.
3 плюса
Представления добавляются "напрямую" по телефону [view addSubview:subview]
. Представления добавляются «косвенно» такими методами, как панели вкладок или панели навигации, которые меняют подвиды.
Каждый раз, когда вы звоните [view addSubview:subviewController.view]
, вам следует позвонить [subviewController viewWillAppear:NO]
(или ДА в зависимости от вашего случая).
У меня была эта проблема, когда я внедрил свою собственную систему управления корневыми представлениями для подэкрана в игре. Добавление вызова к viewWillAppear вручную вылечило мою проблему.
Автор: AndrewS Размещён: 22.11.2010 03:213 плюса
Правильный способ сделать это - использовать API-интерфейс UIViewController.
- (void)viewDidLoad {
[super viewDidLoad];
// Do any additional setup after loading the view.
UIViewController *viewController = ...;
[self addChildViewController:viewController];
[self.view addSubview:viewController.view];
[viewController didMoveToParentViewController:self];
}
Автор: Hari Kunwar
Размещён: 28.07.2015 04:47
2 плюса
Я использую этот код для контроллеров push и pop view:
От себя:
[self.navigationController pushViewController:detaiViewController animated:YES];
[detailNewsViewController viewWillAppear:YES];
поп:
[[self.navigationController popViewControllerAnimated:YES] viewWillAppear:YES];
.. и у меня работает нормально.
Автор: Arash Zeinoddini Размещён: 22.06.2012 07:572 плюса
Очень распространенная ошибка заключается в следующем. У вас есть одна точка зрения UIView* a
, а другая - UIView* b
. Вы добавляете b в a как подпредставление. Если вы попытаетесь вызвать viewWillAppear в b, он никогда не будет запущен, потому что это подпредставление
1 плюс
Я не уверен на 100% в этом, но я думаю, что добавление представления в иерархию представлений напрямую означает обращение -addSubview:
к представлению контроллера представления (например, [viewController.view addSubview:anotherViewController.view]
) вместо помещения нового контроллера представления в стек контроллера навигации.
1 плюс
Я думаю, что добавление подпредставления не обязательно означает, что представление появится, поэтому нет автоматического вызова метода класса, который будет
Автор: winston Размещён: 25.05.2009 06:051 плюс
Я думаю, что они имеют в виду «напрямую», подключая вещи точно так же, как это делает шаблон xcode «Navigation Application», который устанавливает UINavigationController в качестве единственного подпредставления UIWindow приложения.
Использование этого шаблона - единственный способ, с помощью которого я смог получить методы Will / Did / Appear / Disappear, вызываемые для объекта ViewControllers, после нажатия / выталкивания этих контроллеров в UINavigationController. Ни одно из других решений в ответах здесь не работало для меня, включая реализацию их в RootController и передачу их через (дочерний) NavigationController. Эти функции (будут / делались / появляются / исчезают) вызывались в моем RootController только при отображении / скрытии ВК высшего уровня, моих «логинов» и навигационных ВК, а не суб-ВК в контроллере навигации, поэтому у меня не было возможности «передать их» в Nav VC.
Я закончил тем, что использовал функцию делегата UINavigationController для поиска конкретных переходов, которые требовали дополнительных функций в моем приложении, и это работает, но это требует немного больше работы для того, чтобы и симулировать исчезающую и появляющуюся функциональность.
Кроме того, принципиально важно заставить его работать после того, как я сегодня часами бьюсь об эту проблему. Будем весьма благодарны за любые фрагменты рабочего кода, использующие пользовательский RootController и дочерний VC для навигации.
Автор: Bogatyr Размещён: 15.06.2010 03:501 плюс
На случай, если это кому-нибудь поможет. У меня была похожая проблема, когда мой ViewWillAppear
не стреляет UITableViewController
. После долгих тренировок я понял, что проблема была в том, UINavigationController
что управляющий мой UITableView
не в корневом представлении. Как только я это исправлю, теперь он работает как чемпион.
1 плюс
У меня просто была эта проблема, и мне потребовалось 3 полных часа (2 из которых - поиск в Google), чтобы решить ее.
Помогло то, что нужно было просто удалить приложение с устройства / симулятора, очистить, а затем снова запустить .
надеюсь, это поможет
Автор: Finn Gaida Размещён: 21.09.2013 06:181 плюс
[self.navigationController setDelegate:self];
Установите делегата на корневой контроллер представления.
Автор: Gaurav Размещён: 23.11.2010 01:361 плюс
Для Свифта. Сначала создайте протокол для вызова того, что вы хотели вызвать в viewWillAppear
protocol MyViewWillAppearProtocol{func myViewWillAppear()}
Во-вторых, создать класс
class ForceUpdateOnViewAppear: NSObject, UINavigationControllerDelegate {
func navigationController(_ navigationController: UINavigationController, willShow viewController: UIViewController, animated: Bool){
if let updatedCntllr: MyViewWillAppearProtocol = viewController as? MyViewWillAppearProtocol{
updatedCntllr.myViewWillAppear()
}
}
}
В-третьих, сделайте экземпляр ForceUpdateOnViewAppear членом соответствующего класса, который имеет доступ к контроллеру навигации и существует до тех пор, пока существует контроллер навигации. Это может быть, например, контроллер корневого представления контроллера навигации или класс, который его создает или представляет. Затем назначьте экземпляр ForceUpdateOnViewAppear свойству делегата контроллера навигации как можно раньше.
Автор: Vadim Motorine Размещён: 20.12.2018 06:030 плюса
В моем случае проблема была с пользовательской анимацией перехода. Когда набор modalPresentationStyle = .custom
viewWillAppear
не называется
в пользовательском классе анимация перехода необходимо вызвать методы:
beginAppearanceTransition
иendAppearanceTransition
0 плюса
В моем случае это была просто странная ошибка в эмуляторе ios 12.1. Исчез после запуска на реальном устройстве.
Автор: coldembrace Размещён: 29.01.2019 07:250 плюса
Я создал класс, который решает эту проблему. Просто установите его в качестве делегата вашего контроллера навигации и внедрите простой один или два метода в вашем контроллере представления - которые будут вызываться, когда представление будет показано или было показано через NavigationController
Автор: GregJaskiewicz Размещён: 21.02.2019 10:310 плюса
ViewWillAppear - это метод переопределения класса UIViewController, поэтому добавление subView не вызовет viewWillAppear, но при представлении push, pop, show, setFront или popToRootViewController из viewController будет вызван viewWillAppear для представленного viewController.
Автор: Abu Ul Hassan Размещён: 21.02.2019 10:520 плюса
Спасибо iOS 13.
ViewWillDisappear
,ViewDidDisappear
,ViewWillAppear
ИViewDidAppear
не будет вызван на контроллере представления Предъявление КСН 13 , который использует новый модальное представление , которое не покрывает весь экран.
Кредиты собираются на Арек Холко . Он действительно спас мой день.
Автор: BilalReffas Размещён: 14.06.2019 01:54-2 плюса
Я не уверен, что это та же проблема, которую я решил.
В некоторых случаях метод не выполняется обычным способом, таким как «[self methodOne]».
Пытаться
- (void)viewWillAppear:(BOOL)animated
{
[self performSelector:@selector(methodOne)
withObject:nil afterDelay:0];
}
Автор: Sean
Размещён: 16.11.2011 07:35
-3 плюса
В любое время у вас должен быть активен только 1 UIViewController. Любые подпредставления, которыми вы хотите манипулировать, должны быть именно такими - subVIEWS - т.е. UIView.
Я использую простую технику для управления своей иерархией представлений, и мне еще не приходилось сталкиваться с проблемой, так как я начал что-то делать таким образом. Есть 2 ключевых момента:
- один UIViewController должен использоваться для управления "стоимостью экрана" вашего приложения
- используйте UINavigationController для смены представлений
Что я имею в виду под «стоимостью экрана»? Это немного расплывчато, но обычно это функция или раздел вашего приложения. Если у вас есть несколько экранов с одним и тем же фоновым изображением, но с разными оверлеями / всплывающими окнами и т. Д., Это должен быть 1 контроллер представления и несколько дочерних представлений. Вы никогда не должны работать с двумя контроллерами представления. Обратите внимание, что вы все еще можете создать экземпляр UIView в одном контроллере представления и добавить его в качестве подпредставления другого контроллера представления, если вы хотите, чтобы определенные области экрана отображались в нескольких контроллерах представления.
Что касается UINavigationController - это ваш лучший друг! Отключите панель навигации и укажите «Нет» для анимации, и у вас есть отличный способ переключения экранов по требованию. Вы можете выдвигать и выдвигать контроллеры представления, если они находятся в иерархии, или вы можете подготовить массив контроллеров представления (включая массив, содержащий один VC) и установить его в качестве стека представления, используя setViewControllers. Это дает вам полную свободу менять ВК, в то же время получая все преимущества работы в рамках ожидаемой модели Apple и обеспечения надлежащего запуска всех событий и т. Д.
Вот что я делаю каждый раз, когда запускаю приложение:
- начать с оконного приложения
- добавить UINavigationController в качестве rootViewController окна
- добавить все, что я хочу, чтобы мой первый UIViewController был rootViewController контроллера nav
(примечание, начинающееся с окон, это просто личное предпочтение - мне нравится создавать вещи самостоятельно, поэтому я точно знаю, как они создаются. Это должно хорошо работать с шаблоном на основе представления)
Все события происходят правильно и в основном жизнь хороша. Затем вы можете тратить все свое время на написание важных частей вашего приложения, не беспокоясь о попытках вручную взломать иерархию представлений.
Автор: Nigel Flack Размещён: 17.09.2011 11:05Вопросы из категории :
- iphone Как мне дать моим веб-сайтам значок для iPhone?
- iphone iPhone веб-приложения, шаблоны, рамки?
- iphone Приложение для iPhone, которое получает доступ к структуре Core Location через Интернет
- iphone Tips for a successful AppStore submission?
- iphone Могу ли я написать нативные приложения для iPhone с использованием Python
- iphone Изучение OpenGL ES 1.x
- ios Приложение для iPhone в ландшафтном режиме, системы 2008
- ios Как программно отправить смс на айфон?
- ios Как я могу разработать для iPhone, используя машину для разработки Windows?
- ios Как мне определить размер UITextView для его содержимого?
- cocoa-touch iPhone viewWillAppear не стреляет
- cocoa-touch Как показать индикатор загрузки в верхней строке состояния
- cocoa-touch Как сохранить картинку в фотобиблиотеку iPhone?