Подтвердить что ты не робот

IOS: поведение addSubview по-разному между iOS 4.3 и 5.0

при кодировании в iOS 4.3 до этого, я обнаружил, что при добавлении представления контроллера представления в другое представление с помощью [superview addSubView:controller.view] экземпляр контроллера не получит сообщение -viewWillAppear/viewDidAppear, чем я обнаружил такую ​​же проблему в некотором потоке в переполнении стека. После этого я вручную вызываю -viewWillAppear/-viewDidAppear по мере необходимости.

но после обновления до iOS 5.0 произошло некорректное поведение UIView. Наконец, я обнаружил, что в iOS 5, [superview addSubView:controller.view], автоматически отправит сообщение -viewWillAppear/-viewDidAppear на экземпляр контроллера, а также мои ручные вызовы, при каждом действии контроллера его поведение будет дублироваться.

и я также нашел аналогичную проблему: iOS 5: -viewWillAppear не вызывается после отклонения модальности в iPad

Теперь проблема заключается в том, что после поиска документов Apple я не нашел явного документа для проверки этих проблем. Я даже задаюсь вопросом, является ли это гарантированным показателем жизненного цикла просмотра в iOS 5.0.

Кто-нибудь исправляет подобные проблемы или находит некоторые рекомендации относительно этих различий. Я хочу запустить приложение как в 4.x & 5.x iOS.

4b9b3361

Ответ 1

В iOS 4 вам нужно было вручную вызвать -viewWillAppear, -viewWillDisappear и т.д. при добавлении или удалении представления из вашей иерархии представлений. Они автоматически вызываются в iOS 5, если представление добавляется или удаляется из иерархии окон. К счастью, у iOS 5 есть метод в UIViewController, который вы можете переопределить, чтобы вернуть поведение к работе с iOS 4. Просто добавьте это в свой UIViewController:

-(BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
   return NO;
}

Это, пожалуй, самое простое решение, если вы поддерживаете как iOS 4, так и iOS 5. Как только вы отмените поддержку iOS 4, вы можете подумать о том, чтобы изменить код, чтобы использовать более новый подход при замене представлений.

Редактировать 5 февраля 2012

По-видимому, эта функция требует, чтобы контроллер детского представления добавлялся к главному контроллеру представления, используя метод addChildViewController:. Этот метод не существует в iOS4, поэтому вам нужно сделать что-то вроде этого:

  if ([self respondsToSelector:@selector(addChildViewController:)] ) {
     [self addChildViewController:childViewController];
  }

Спасибо всем, кто меня исправил.

Ответ 2

Это может быть не ответ на то, что вы хотите, но у меня была такая же проблема.

В моем случае, когда я добавил представление контроллера представления в другое представление контроллера представления как подвью, subview был получен viewWillAppear только в iOS 5.0, а не iOS 4.X.

Итак, я добавил неприятное состояние.

[self.view addSubview:self.viewController.view];
if ([[[UIDevice currentDevice] systemVersion] compare:@"5.0"] == NSOrderedAscending) {
    [self.viewController viewWillAppear:animated];
}

Из iOS 5.0, Apple предоставляет возможность реализовать пользовательские контроллеры представления контейнеров, такие как UINavigationController или UITabController. Я думаю, что это изменение влияет на вызов viewWillAppear.

Эта проблема может быть разрешимой, если мы используем -[UIViewController addChildViewController:].

Ответ 3

Ответы немного неполные. Предположим, у вас есть 2 контроллера вида, ControllerA и ControllerB.

ControllerA.view уже добавлен в окно (это родительский элемент), и вы хотите добавить ControllerB.view в качестве подзадачи ControllerA.

Если вы не добавите ControllerB в качестве дочернего элемента ControllerA во-первых, то автоматически игнорируются функции forForAppearanceAndRotationMethodsToChildViewControllers, и вы все равно будете вызываться iOS5, а это означает, что вы дважды вызовете обратные вызовы контроллера.

Пример в ControllerA:

- (BOOL)automaticallyForwardAppearanceAndRotationMethodsToChildViewControllers {
    return NO;
}

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil];

    [self.view addSubview:self.controllerB.view];
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];
    [self.controllerB viewWillAppear:animated];
}

В ControllerB NSLogging in viewWillAppear:

- (void)viewWillAppear:(BOOL)animated
{
    NSLog("@ControllerB will appear");
}

Это приведет к тому, что iOS5 отобразит это сообщение NSLog дважды. т.е. вы автоматически переноситеAppearanceAndRotationMethodsToChildViewControllers игнорируются.

Чтобы исправить это, вам нужно добавить контроллер B в качестве дочернего элемента контроллера a.

Назад в классе ControllerA:

- (void)viewDidLoad
{
    [super viewDidLoad];
    self.controllerB = [[ControllerB alloc] initWithNibName:@"ControllerB" bundle:nil];
    if ([self respondsToSelector:@selector(addChildViewController:)])
        [self addChildViewController:self.controllerB];

    [self.view addSubview:self.controllerB.view];
}

Теперь это будет работать как в iOS4, так и в iOS5, не прибегая к ужасному взлому проверки строк версии iOS, но вместо этого проверяет, доступна ли функция, которую мы предоставляем.

Надеюсь, что это поможет.

Ответ 4

Это поведение iOS5:
viewWillAppear, viewDidAppear,... выполняются автоматически после addSubView: для iOS5.

Таким образом, для iOS5 не нужно вручную выполнять эти методы по мере необходимости для iOS < 5.0.



Исправление может быть:

if ([[UIDevice currentDevice].systemVersion doubleValue] < 5.0) {
...execute viewWillAppear or other
}

Ответ 5

С помощью этого метода вы знаете, какое os u использовать и поставить условие, если оно меньше 5.0 или другое

[[UIDevice currentDevice] systemVersion]

Ответ 6

view{Will,Did}Appear, view{Will,Did}Disappear - это функции на Контроллерах просмотра, а не на представлениях. Эти функции вызывают контроллеры представлений SDK, которые должны управлять другими контроллерами представлений, например. UITabBarController, UINavigationBarController.

Если вы управляете контроллерами суб-представлений самостоятельно, вы должны называть их явно (и в правильном порядке - хотя у вас есть все основания для этого). Модальное представление, не получающее этих призывов об увольнении модального представления, просто потому, что его никто не может назвать. Инкапсулируйте контроллер корневого представления в UINavigationController (и, если хотите, скройте панель навигации), а затем откройте контроллер модального представления. После его увольнения или поп-музыки viewWillAppear вызывается.

Ответ 7

После просмотра всех доказательств, я думаю, что лучше всего не использовать viewDidAppear и т.д. для просмотров, которые подвержены этой ошибке ios 4/ios 5. Вместо этого создайте собственный класс (например, viewDidAppearCustom) и вызовите его самостоятельно. таким образом, вы можете гарантировать, что яблоко не изменит sdk и не повредит вам. Здесь есть большой блог, посвященный этой проблеме:

http://gamesfromwithin.com/view-controller-notification-changes-on-ios5