首页
学习
活动
专区
圈层
工具
发布
首页
学习
活动
专区
圈层
工具
社区首页 >问答首页 >如何在两个使用自定义UIViewController的UIView之间进行转换而不会造成内存泄漏?

如何在两个使用自定义UIViewController的UIView之间进行转换而不会造成内存泄漏?
EN

Stack Overflow用户
提问于 2011-03-16 04:12:17
回答 3查看 2K关注 0票数 1

我正在尝试使用视图模拟翻书。当查看一本打开的书时,每个UIView显示两页(左和右)。翻页时,应该会显示一个新的UIView。我目前的方法是创建一个带有空白根UIView的自定义UIViewController,并使页面成为子视图。当我添加一个新的子视图时,我从上一个添加的子视图过渡到新的子视图。一旦转换完成,我想删除之前的最后一个子视图,因为它不再需要--它不再可见并占用内存。

本质上,它是这样的:

代码语言:javascript
运行
复制
UIView * myOldPageView = [[self.view subviews] lastObject];
[self.view addSubview:myNewPageView];
// ... transition between the two views
[myOldPageView removeFromSuperview];

这是我对它的初步尝试,失败了,出现了一个神秘的崩溃,没有堆栈跟踪。此方法位于我的自定义UIViewController中:

代码语言:javascript
运行
复制
-(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。如果我不做释放,我会得到一个内存泄漏。

编辑这里是另一种不使用控制器的方法,当旧的页面视图从其superview中删除时会崩溃:

代码语言:javascript
运行
复制
-(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
  }
}

编辑即使我尝试在添加新的子视图后立即删除它,我也会崩溃,没有过渡动画:

代码语言:javascript
运行
复制
 -(void) switchToView:(UIView *) screen {
   [self.view addSubview:screen];
   if (3 < [[self.view subviews] count]) {
     [screen removeFromSuperview]; // <- crash
    }
  }

编辑我现在强烈认为问题出在释放添加的视图,这意味着它与动画或视图控制器无关。

EN

回答 3

Stack Overflow用户

发布于 2011-03-16 04:25:35

您可能想看看UIView方法transitionFromView:toView:duration:options:completion:

使用options:,您可以指定页面卷曲效果。

这个方法是从fromView参数中的视图转换到toView参数中的视图的一种简单方法。默认情况下,视图层次结构中的视图被toView中的视图替换为fromView中的视图。如果这两个视图都已经是视图层次结构的一部分,则可以在options参数中包含UIViewAnimationOptionShowHideTransitionViews选项以隐藏或显示它们。

票数 3
EN

Stack Overflow用户

发布于 2011-03-16 04:16:42

尝试您想要处理的视图的removeFromSuperview。

票数 0
EN

Stack Overflow用户

发布于 2011-03-16 07:34:22

这只是文档中的内容,但现在我们开始:使用NavigationController并在

代码语言:javascript
运行
复制
- (void)setViewControllers:(NSArray *)viewControllers animated:(BOOL)animated

其中添加到数组的最后一项成为导航堆栈的顶部项。从文档中:

如果启用了动画,此方法将根据items数组中的最后一项是否已在导航堆栈中来确定要执行哪种类型的转换。如果视图控制器当前在堆栈中,但不是最顶层的项,则此方法使用pop转换;如果它是最顶层的项,则不执行转换。如果视图控制器不在堆栈上,则此方法使用推式转换。只执行一次转换,但当该转换完成时,堆栈的所有内容都将替换为新的视图控制器。例如,如果控制器A、B和C在堆栈上,而您设置了控制器D、A和B,则此方法使用弹出过渡,生成的堆栈包含控制器D、A和B。

也就是说,如果你有视图控制器A和B,创建数组

{A,B} {B,A} {A} {B}。

假设你从第一页A开始,然后你想要推转到B,将数组设置为{B},请注意:

如果视图控制器不在堆栈上,则此方法使用推式过渡。

下一次,将其设置为{A},依此类推,以进行正向迭代。现在,如果您想要从B到A的pop转换,请注意

如果视图控制器当前在堆栈中,但不是最上面的项,则此方法使用pop转换;

您将其设置为{ B,A},反之亦然,从A到B。当然,在动画(?)之后,只需返回到{A}和{B}数组以返回到起始点-如果视图控制器已经是最上面的,则不执行任何转换。祝你好运;)

票数 0
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/5317437

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档