这个NSView被解除分配到哪里会导致错误的访问错误?

时间:2013-12-24 03:45:40

标签: objective-c macos cocoa automatic-ref-counting nsview

我正在编写一个应用程序,用户应该可以单击按钮并切换视图。我创建了IBActions,在所需的视图上加载我的方法switchSubView,但是这样做有一些问题。我目前已经编写了一些方法来设置通过Interface Builder作为IBOutlets连接的两个NSViews之间的转换动画。我能够使用这些方法在两个视图之间进行转换,但是当我尝试从初始视图切换到另一个视图,然后切换到另一个视图,然后切换回来时,我得到EXC_BAD_ACCESS。我似乎无法调试问题。调试器显示两个NSView对象以指向不同的内存位置。为了澄清,我想在整个应用程序执行期间重用这些视图。我不希望任何意见被取消分配。

以下是代码:

- (void)switchSubViews:(NSView *)firstView withView:(NSView *)secondView {
    [firstView setSubviews:[NSArray array]];
    [self prepareViews:firstView];
    [[firstView animator] addSubview:secondView];
}

/* Make a "move" animation effect. */
- (void)prepareViews:(NSView *)prepareView {
    CATransition * transition = [CATransition animation];
    [transition setType:kCATransitionPush];
    [transition setSubtype:kCATransitionFromRight];
    [prepareView setAnimations:[NSDictionary dictionaryWithObject:transition forKey:@"subviews"]];
    [prepareView setWantsLayer:YES];
}

基本上,我会这样称呼它,给出initialView和newView:

[self switchSubViews:initialView withView:newView];

任何人都可以帮我调试吗?

感谢。

更新:在注释掉for循环和removeFromSuperview代码进行调试后,我仍然收到错误的访问错误。视图的属性设置为@property (nonatomic, strong),因此不应保留视图?如果没有,我如何在启用ARC的情况下明确保留我的NSView?是否可以告诉ARC保留它,或者它是否已经保留了视图,因为它是使用@property(非原子,强)设置的?

第二次更新:我研究了一下,发现我可以通过创建一个指向该对象的强指针来使ARC保留该对象。我通过创建实例变量来尝试它:

@interface AppDelegate : NSObject <NSApplicationDelegate, NSWindowDelegate> {
    /* Some instance variables here... */
    __strong NSView * retainFirstView;
    __strong NSView * retainSecondView;
}

@property (nonatomic, strong) NSView * retainFirstView;
@property (nonatomic, strong) NSView * retainSecondView;

然后在.m文件中:

#import <Quartz/Quartz.h> /* Animation. */
#import "AppDelegate.h"
/* Some other imports necessary... */

@implementation AppDelegate

@synthesize retainFirstView;
@synthesize retainSecondView; 

/* Some subview switching code... */
[self setRetainFirstView:firstView];
[self setRetainSecondView:secondView];

@end

但我仍然收到错误。似乎我正在交换的观点一直被取消分配。我花了很多时间在这上面并且无法摆脱错误。任何帮助,将不胜感激。如果这不是保留视图的正确方法,请告诉我。

更新3:要进行测试,我暂时禁用了ARC并在调用setSubviews或addSubview之前执行了此操作:

[firstView retain]; 
[secondView retain];

它仍然失败了。我很困惑,因为我不再看到导致释放的原因。

更新4:我通过执行产品检查了发送到解除分配对象的僵尸和消息 - &gt; Xcode中的个人资料,令我惊讶的是,我没有得到任何通知。我很困惑为什么会这样。

1 个答案:

答案 0 :(得分:3)

您收到EXC_BAD_ACCESS,因为如果没有其他内容保留,则调用-removeFromSuperview将取消分配该视图。正在被释放的视图(因此具有指向垃圾的对象指针)很可能稍后被传递到-switchSubviews:withView,从而导致崩溃。在调用-removeFromSuperview之前,您应该始终保留稍后将要使用的视图,以确保它们不会被释放。

作为旁注,-switchSubviews:withView:的代码不必要地复杂化。它可以简化为:

- (void)switchSubViews:(NSView *)firstView withView:(NSView *)secondView {
    firstView.subviews = [NSArray array];
    [self prepareViews:firstView];
    [[firstView animator] addSubview:secondView];
}