EXC_BAD_ACCESS 当我关闭窗口时,这也是我的应用程序的委托

Ily*_*okh 0 macos cocoa exc-bad-access xcode4 automatic-ref-counting

EXC_BAD_ACCESS我编写了一个 Cocoa 应用程序,当我关闭应用程序窗口时出现错误。我读到这个错误通常意味着内存问题,但我已经ARC mode打开并且不需要关心释放等(xCode 禁止我调用这个函数并自动管理内存)。

错误指向return NSApplicationMain(argc, (const char **)argv);主函数中的行。

这是我的应用程序的代码:

.h 文件:

@interface MainDreamer : NSWindow <NSWindowDelegate> 
{    
    NSTextField *dreamField;
    NSTableView *dreamTable;    
    NSImageView *dreamview;

    NSMutableArray *dreamlist;  
    NSMutableArray *dataset;
}

@property (nonatomic, retain) IBOutlet NSTextField *dreamField;
@property (nonatomic, retain) IBOutlet NSTableView *dreamTable;
@property (nonatomic, retain) IBOutlet NSImageView *dreamview;
@property (nonatomic, retain) IBOutlet NSMutableArray *dreamlist;
@property (nonatomic, retain) IBOutlet NSMutableArray *dataset;
@property (assign) IBOutlet NSWindow *window;

@end
Run Code Online (Sandbox Code Playgroud)

.m 文件:

@implementation MainDreamer

@synthesize window;
@synthesize dataset;
@synthesize dreamField;
@synthesize dreamlist;
@synthesize dreamview;
@synthesize dreamTable;

- (void)applicationDidFinishLaunching:(NSNotification *)aNotification{
    NSString *applicationPath = [[NSBundle mainBundle] bundlePath];
    NSString *filename = [applicationPath stringByAppendingPathComponent:@"dreams"];
    NSLog(self.description);

    dreamlist = [[NSMutableArray alloc] init];  
    dataset = [[NSMutableArray alloc] init];
    dataset = [NSKeyedUnarchiver unarchiveObjectWithFile:filename];
    if([dataset count] != 0) {
        int i = 0;
        while (i < [dataset count]) { 
            Dream *dr = [[Dream alloc] init];
            dr = [dataset objectAtIndex:i];
            [dreamlist addObject: dr.dreamname];         
            i++;
        }
    }    
    [dreamTable reloadData]; 
}

-(void)applicationWillTerminate:(NSNotification *)notification{       
    NSString *applicationPath = [[NSBundle mainBundle] bundlePath];
    NSString *filename = [applicationPath stringByAppendingPathComponent:@"dreams"];
    [NSKeyedArchiver archiveRootObject:dataset toFile:filename];
    NSLog(@"finish");
}

- (void) mouseUp:(NSEvent *)theEvent{
    long index = [dreamTable selectedRow];
    Dream *dr = [[Dream alloc] init];
    dr = [dataset objectAtIndex:index];
    dr.dreampicture = dreamview.image;
    [dataset replaceObjectAtIndex:index withObject:dr];
    NSLog(self.description);
}

- (void) tableViewSelectionDidChange: (NSNotification *) notification{
    long row = [dreamTable selectedRow];
    Dream *dr = [[Dream alloc] init];
    dr = [dataset objectAtIndex: row];
    if(dr.dreampicture != NULL) 
        dreamview.image = dr.dreampicture;
    NSLog(@"selected row changed");
}
Run Code Online (Sandbox Code Playgroud)

“梦想”班:

@interface Dream : NSObject <NSCoding>
{
    NSString *dreamname;
    NSImage *dreampicture;
}

@property (retain) NSString* dreamname;
@property (retain) NSImage* dreampicture;

-(id)initWithCoder:(NSCoder *)aDecoder;
-(void)encodeWithCoder:(NSCoder *)aCoder;

@end
Run Code Online (Sandbox Code Playgroud)

出了什么问题,为什么EXC_BAD_ACCESS会发生?我提醒我有带有自动引用计数(ARC)的 xCode 4

谢谢

更新

我使用 Profile 来查找僵尸事件。所以我发现了这一点:一条 Objective-C 消息被发送到一个已释放的对象(僵尸(位于地址 0x108d85230)

负责任的来电者 -[NSApplication(NSWindowCache) _checkForTerminateAfterLastWindowClosed: saveWindows:]

我在代码中有这个功能:

- (BOOL)applicationShouldTerminateAfterLastWindowClosed:(NSApplication *)sender{
    return TRUE;
}
Run Code Online (Sandbox Code Playgroud)

然而在我发表评论后,这种僵尸事件却不断发生。

Pet*_*sey 7

崩溃是由于您将窗口设为应用程序的委托而引起的。当您关闭窗口时,这是杀死它的最后一个版本,如果这是您打开的最后一个窗口,它会导致应用程序询问其委托是否应该退出。由于您刚刚杀死的窗口应用程序的委托,因此您会发生崩溃。

我对您后续问题的回答中有更长的解释和解决方案建议。