Как переходить между двумя UIView, используя пользовательский UIViewController без утечек памяти? - PullRequest
1 голос
/ 15 марта 2011

Я пытаюсь смоделировать перелистывание страниц книги, используя представления.Каждый UIView отображает две страницы (левую и правую) при просмотре открытой книги.Когда страница перевернута, должен появиться новый UIView.Мой текущий подход состоит в том, чтобы иметь пользовательский UIViewController с пустым корневым UIView и иметь страницы, которые будут подпредставлениями.Когда я добавляю новое подпредставление, я перехожу из последнего добавленного подпредставления в новое.После завершения перехода я хочу удалить предыдущее последнее подпредставление, потому что оно больше не нужно - оно больше не видно и занимает память.

По сути, это так:

UIView * myOldPageView = [[self.view subviews] lastObject];
[self.view addSubview:myNewPageView];
// ... transition between the two views
[myOldPageView removeFromSuperview];

Вот мой первоначальный удар по нему, который завершается с загадочным сбоем без следа стека.Этот метод в моем пользовательском UIViewController:

-(void) switchToController:(UIViewController *) controller {
    [controller viewWillAppear:YES];        

    if (self.currentScreenController != nil) {
        [self.currentScreenController viewWillDisappear:YES];
    }

    [self.view addSubview:[controller view]];

    if (self.currentScreenController != nil) {
        [[self.currentScreenController view] removeFromSuperview];
        [self.currentScreenController viewDidDisappear:YES];
    }

    self.currentScreenController = controller;

    [controller viewDidAppear:YES];
}

Выполнение [controller release] после вызова этого метода вызывает сбой, что странно, так как счетчик сохранения больше 0. Если я не делаю релизЯ получаю утечку памяти.

[Edit] Вот еще один подход без использования контроллера, который падает, когда старый просмотр страницы удаляется из его суперпредставления:

-(void) switchToView:(UIView *) screen {
  [self.view addSubview:screen];
  [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:screen cache:NO];
  [UIView commitAnimations];
  if (3 < [[self.view subviews] count]) {
    [[[self.view subviews] objectAtIndex:0] removeFromSuperview]; // <- crash
  }
}

[Edit] Даже еслиЯ пытаюсь удалить новое подпредставление сразу после его добавления. Я получаю сбой без анимации перехода:

 -(void) switchToView:(UIView *) screen {
   [self.view addSubview:screen];
   if (3 < [[self.view subviews] count]) {
     [screen removeFromSuperview]; // <- crash
    }
  }

[Редактировать] Я теперь твердо верю, что проблема заключается в освобождении добавленного представления, что означает, что у него нет ничегоделать с анимацией или контроллерами представления.

Ответы [ 3 ]

3 голосов
/ 15 марта 2011

Возможно, вы захотите взглянуть на метод UIView transitionFromView:toView:duration:options:completion:

Используя options:, вы можете указать эффект скручивания страницы.

Из документов: Обсуждение Этот метод представляет собой простой способ перехода от представления в параметре fromView к представлению в параметре toView. По умолчанию представление в fromView заменяется в иерархии представлений представлением в toView. Если оба представления уже являются частью вашей иерархии представлений, вы можете включить параметр UIViewAnimationOptionShowHideTransitionViews в параметр options, чтобы скрыть или показать их.

0 голосов
/ 16 марта 2011

Это только из документов, но здесь мы идем: Используйте NavigationController и манипулируйте массивом в

- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated

, где последний элемент, добавленный в массив, становится верхним элементомстека навигации.Из документов:

Если анимации включены, этот метод решает, какой тип перехода выполнять в зависимости от того, находится ли последний элемент в массиве элементов в стеке навигации.Если контроллер представления в настоящее время находится в стеке, но не является самым верхним элементом, этот метод использует всплывающий переход;если это самый верхний элемент, переход не выполняется.Если контроллер представления не находится в стеке, этот метод использует push-переход.Выполняется только один переход, но когда этот переход завершается, все содержимое стека заменяется новыми контроллерами представления.Например, если контроллеры A, B и C находятся в стеке, и вы устанавливаете контроллеры D, A и B, этот метод использует pop-переход, и результирующий стек содержит контроллеры D, A и B.

т.е. если у вас есть контроллеры вида A a B, создайте массивы

{A, B} {B, A} {A} {B}.

и, скажем, вамначните с первой страницы, обозначающей A. Затем вы хотите принудительный переход к B, установите для массива значение {B}, обратите внимание, что:

Если контроллер представления не находится в стеке, этот метод используетpush-переход.

В следующий раз установите для него значение {A} и т. д. для итерации в прямом направлении.Теперь, если вы хотите всплывающий переход от B к A, обратите внимание, что

Если контроллер представления в данный момент находится в стеке, но не является самым верхним элементом, этот метод использует всплывающий переход;

вы устанавливаете его на {B, A} и наоборот от A до B. Затем, конечно, после анимации (?), Просто вернитесь к массивам {A} и {B}, чтобы вернуться к исходномуточка - если контроллер представления уже является верхним, переход не выполняется.Удачи;)

0 голосов
/ 15 марта 2011

Попробуйте удалить из SuperSview представление, которое вы хотите удалить.

Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...