我正在编写一个应用程序,用户应该可以单击按钮并切换视图。我创建了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中的个人资料,令我惊讶的是,我没有得到任何通知。我很困惑为什么会这样。
答案 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];
}