切换视图EXC_BAD_ACCESS

时间:2011-06-03 14:03:40

标签: iphone uiview

我在界面构建器中创建了一个UIView(除了原始视图)。

@interface TimeLineGrid : UIViewController {

UIView *toggleView;

}

@property (nonatomic, retain) IBOutlet UIView *toggleView;

我也合成了它。我已经实现了一个滑动手势,以便在向上滑动时添加切换视图,当向下滑动时,切换视图将被删除。

-(void)swipedUp {

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:2.0f];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];

    [self.view addSubview:self.toggleView];

    [UIView commitAnimations];



}

-(void)swipedDown {

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:2.0f];

    [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];

    [self.toggleView removeFromSuperview];

    [UIView commitAnimations];

}

当我向上滑动一次并在此之后向下滑动时,它工作正常。但是当我再次向上滑动时,它会因EXC_BAD_ACCESS错误而崩溃。我知道这与保留计数增加有关,当我添加子视图并减少当我删除子视图时。有人能否对此有所了解?如何实现此切换?

编辑: 我的视图层次结构如下:

->UIView (toggleView)
->UIView (mainView to which toggleView is being added)
 -->UIToolBar

4 个答案:

答案 0 :(得分:3)

您能否应用此类更改并告知哪些UIView确实存在问题。

  1. 打开XCode /产品/编辑方案......
  2. 移至环境变量,然后单击加号以添加变量
  3. 添加变量NSZombieEnables - value:YES
  4. 添加变量MallocStackLoggingNoCompact - value:1
  5. 启动应用程序后,当您调用它时,您将看到确切处理了哪个对象。

答案 1 :(得分:3)

最有可能的是,当您致电[self.toggleView removeFromSuperview];时,该视图正在发布。我建议您稍微重新构建一下代码。

由于您在IB中创建视图,因此在头文件中将其声明为

IBOutlet UIView *toggleView;

包含属性调用或合成。由于您没有设置或获取toggleView,只需通过指针引用它。

在实现中,将指针设置为nil中的viewDidUnload并在dealloc中释放它。然后,按如下方式调整切换方法:

-(void)swipedUp {
    if (![toggleView superview]) {

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:2.0f];

        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromLeft forView:self.view cache:NO];

        [self.view addSubview:toggleView];

        [UIView commitAnimations];
    }
}

-(void)swipedDown {

    if ([toggleView superview]) {

        [UIView beginAnimations:nil context:nil];
        [UIView setAnimationDuration:2.0f];

        [UIView setAnimationTransition:UIViewAnimationTransitionFlipFromRight forView:self.view cache:NO];

        [toggleView removeFromSuperview];

        [UIView commitAnimations];
    }
}

此处,if子句将捕获用户连续两次刷新而不响应第二次滑动的事件。另请注意,这会使用toggleView代替self.toggleView

这应解决问题。

答案 2 :(得分:1)

我建议您制作要展示/隐藏的视图,容器视图的子视图。然后,在动画块中首先删除消失的视图并添加要显示的视图。例如:

@interface TimeLineGrid : UIViewController {
    // declare the views you want to flip between
    UIView *mainView;
    UIView *toggleView;
}

@property (nonatomic, retain) IBOutlet UIView *mainView;
@property (nonatomic, retain) IBOutlet UIView *toggleView;

在您的实施中:

// self.view is the container view (an instance of UIView).
// Initially, self.mainView is a subview of self.view

-(void)transitionFromView:(UIView *)fromView toView:(UIView *)toView withAnimation:(UIViewAnimationTransition)animation {

    if ([toView superview]) {
        // toView already shown
        return;
    }

    [UIView beginAnimations:nil context:nil];
    [UIView setAnimationDuration:2.0f];

    [UIView setAnimationTransition:animation forView:self.view cache:NO];

    [self.view removeFromSuperview:fromView];
    [self.view addSubview:toView];

    [UIView commitAnimations];

}

-(void)swipedUp {
    [self transitionFromView:self.mainView 
                      toView:self.toggleView 
               withAnimation:UIViewAnimationTransitionFlipFromLeft];
}

-(void)swipedDown {
    [self transitionFromView:self.toggleView 
                      toView:self.mainView 
               withAnimation:UIViewAnimationTransitionFlipFromRight];
}

但请注意,现在不鼓励使用方法setAnimationTransition:forView:cache:。 Apple建议使用UIView transitionWithView:duration:options:animations:completion:方法(请参阅UIView reference)。

我希望这有帮助!

答案 3 :(得分:1)

我已经创建了一个包含UITabbar的应用程序,但我使用UIButton获得了相同的行为。

当您不释放调用removeFromSuperview的对象时会发生这种情况,当我从viewControllers视图中删除UIButton时,我的效果相同。

在我的情况下,我仍然可以看到按钮,如果我点击它,我会得到一个异常,例如无法识别的选择器发送到NSCFString类型的对象。

但是,如果我更改了标签然后返回到我的视图控制器,此按钮在从我的视图中删除后显示在该视图控制器中,然后它就消失了。

所以我的结论是,如果您不释放您正在调用的对象removeFromSuperview,那么如果您将对象作为类的实例变量并将其添加到视图中,则应用程序将显示一些意外行为以编程方式addSubView方法。

你有什么选择: -

  1. 您可以在uiview或其子类对象上调用removeFromSuperview并在其上调用release或将其设为nil。

  2. 您可以使用hidden属性隐藏或取消隐藏这些对象,而不是从superview中删除它们。

  3. (我还没有完全尝试过)您可以在类实现中创建一个UIView对象,然后将其添加为subview,然后将其分配给您的实例变量使用点运算符,然后释放先前创建的UIView对象。

  4. 我不知道我的答案可能会对你有什么帮助,但我认为与其他人分享你的经验会很好。