将对象添加到数组时程序崩溃

时间:2014-09-13 17:03:43

标签: objective-c arrays macos cocoa

我有一个Objective-C类SBUSBDevice,它代表用户插入系统的USB驱动器。在我的一个视图控制器中,我获取包含这些对象的字典,将它们添加到数组中,并尝试使用此数组执行操作:

#import "SBUSBSetupWindowController.h"
#import "SBAppDelegate.h"
#import "SBUSBDevice.h"

@interface SBUSBSetupWindowController ()

@property (strong) NSDictionary *usbDictionary;
@property (weak) IBOutlet NSTableView *tableView;
@property (weak) IBOutlet NSButton *enableStartupDiskButton;

@property (strong) NSMutableArray *usbArray;

@end

@implementation SBUSBSetupWindowController

- (id)initWithWindow:(NSWindow *)window {
self = [super initWithWindow:window];
if (self) {
    // Initialization code here.
    self.usbDictionary = [[(SBAppDelegate *)[NSApp delegate] usbDictionary] copy];

    self.usbArray = [[NSMutableArray alloc] initWithCapacity:[self.usbDictionary count]];
    [self.usbDictionary enumerateKeysAndObjectsUsingBlock:^(id key, SBUSBDevice *object, BOOL *stop) {
        NSLog(@"%@ = %@", key, object);
        [self.usbArray addObject:object]; // <-- CRASH OCCURS HERE
    }];
}
    return self;
}

不幸的是,当我运行代码时,它会抛出以下异常:

[SBUSBDevice copyWithZone:]: unrecognized selector sent to instance 0x6080004602c0

据我所知,我不是要复制任何SBUSBDevice个实例,因此不需要执行copyWithZone:。我在我的应用程序的其他区域使用相同的技术,略有不同,它们都有效。为什么抛出这个异常?

以下是最初创建SBUSBDevice个对象的方法。请注意,它们被放入字典中,稍后由上面的代码引用:

- (void)detectAndSetupUSBs {
if (!self.usbDictionary) {
    self.usbDictionary = [[NSMutableDictionary alloc] initWithCapacity:10];
}

NSArray *volumes = [[NSFileManager defaultManager] mountedVolumeURLsIncludingResourceValuesForKeys:nil options:0];
BOOL isRemovable, isWritable, isUnmountable;
NSString *description, *volumeType;

BOOL acceptHFSDrives = [[NSUserDefaults standardUserDefaults] boolForKey:@"AcceptHFSDrives"];

for (NSURL *mountURL in volumes) {
    NSString *usbDeviceMountPoint = [mountURL path];
    if ([[NSWorkspace sharedWorkspace] getFileSystemInfoForPath:usbDeviceMountPoint isRemovable:&isRemovable isWritable:&isWritable isUnmountable:&isUnmountable description:&description type:&volumeType]) {
        if (isRemovable && isWritable && isUnmountable) {
            NSLog(@"Detected eligible volume at %@. Type: %@", usbDeviceMountPoint, volumeType);

            if ([usbDeviceMountPoint isEqualToString:@"/"]) {
                // Don't include the root partition in the list of USBs.
                continue;
            }
            else {
                if ([volumeType isEqualToString:@"msdos"] ||
                    ([volumeType isEqualToString:@"hfs"] && acceptHFSDrives)) {
                    SBUSBDevice *usbDevice = [[SBUSBDevice alloc] init];
                    usbDevice.path = usbDeviceMountPoint;
                    usbDevice.name = [usbDeviceMountPoint lastPathComponent];
                    [SBAppDelegate uuidForDeviceName:usbDeviceMountPoint];

                    self.usbDictionary[usbDevice.name] = usbDevice;
                }
            }
        }
    }
}
}

这是异常的文本(插入的每个USB驱动器都会发生一次):

2014-09-17 15:59:50.586 Mac Linux USB Loader[875:303] -[SBUSBDevice copyWithZone:]: unrecognized selector sent to instance 0x608000469140
2014-09-17 15:59:50.596 Mac Linux USB Loader[875:303] (
0   CoreFoundation                      0x00007fff8de8725c __exceptionPreprocess + 172
1   libobjc.A.dylib                     0x00007fff85e2ae75 objc_exception_throw + 43
2   CoreFoundation                      0x00007fff8de8a12d -[NSObject(NSObject) doesNotRecognizeSelector:] + 205
3   CoreFoundation                      0x00007fff8dde5272 ___forwarding___ + 1010
4   CoreFoundation                      0x00007fff8dde4df8 _CF_forwarding_prep_0 + 120
5   AppKit                              0x00007fff8aa79186 -[NSCell _setContents:] + 74
6   AppKit                              0x00007fff8aa95f5c -[NSCell setObjectValue:] + 317
7   AppKit                              0x00007fff8aa95c8e -[NSTextFieldCell setObjectValue:] + 91
8   AppKit                              0x00007fff8ad13df6 -[NSTableView preparedCellAtColumn:row:] + 589
9   AppKit                              0x00007fff8ad13a5e -[NSTableView _drawContentsAtRow:column:withCellFrame:] + 44
10  AppKit                              0x00007fff8ad13793 -[NSTableView drawRow:clipRect:] + 1629
11  AppKit                              0x00007fff8ad12fed -[NSTableView drawRowIndexes:clipRect:] + 776
12  AppKit                              0x00007fff8abdc331 -[NSTableView drawRect:] + 1484
13  AppKit                              0x00007fff8abb7557 -[NSView(NSInternal) _recursive:displayRectIgnoringOpacity:inGraphicsContext:CGContext:topView:shouldChangeFontReferenceColor:] + 1082
14  AppKit                              0x00007fff8abb700d __46-[NSView(NSLayerKitGlue) drawLayer:inContext:]_block_invoke + 186
15  AppKit                              0x00007fff8abb6e03 -[NSView(NSLayerKitGlue) _drawViewBackingLayer:inContext:drawingHandler:] + 2297
16  AppKit                              0x00007fff8abb64f8 -[NSView(NSLayerKitGlue) drawLayer:inContext:] + 108
17  QuartzCore                          0x00007fff8cb46812 CABackingStoreUpdate_ + 2220
18  QuartzCore                          0x00007fff8cb45f60 ___ZN2CA5Layer8display_Ev_block_invoke + 59
19  QuartzCore                          0x00007fff8cb45f1c x_blame_allocations + 84
20  QuartzCore                          0x00007fff8cb45a2b _ZN2CA5Layer8display_Ev + 1539
21  AppKit                              0x00007fff8abb63c3 _NSBackingLayerDisplay + 235
22  AppKit                              0x00007fff8ab8d74b -[_NSViewBackingLayer display] + 811
23  QuartzCore                          0x00007fff8cb45162 _ZN2CA5Layer17display_if_neededEPNS_11TransactionE + 590
24  QuartzCore                          0x00007fff8cb448b1 _ZN2CA5Layer28layout_and_display_if_neededEPNS_11TransactionE + 35
25  QuartzCore                          0x00007fff8cb4433c _ZN2CA7Context18commit_transactionEPNS_11TransactionE + 236
26  QuartzCore                          0x00007fff8cb43fd6 _ZN2CA11Transaction6commitEv + 388
27  QuartzCore                          0x00007fff8cb54761 _ZN2CA11Transaction17observer_callbackEP19__CFRunLoopObservermPv + 71
28  CoreFoundation                      0x00007fff8ddb7d67 __CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION__ + 23
29  CoreFoundation                      0x00007fff8ddb7cd7 __CFRunLoopDoObservers + 391
30  CoreFoundation                      0x00007fff8dda8e94 CFRunLoopRunSpecific + 340
31  HIToolbox                           0x00007fff8b725a0d RunCurrentEventLoopInMode + 226
32  HIToolbox                           0x00007fff8b7257b7 ReceiveNextEventCommon + 479
33  HIToolbox                           0x00007fff8b7255bc _BlockUntilNextEventMatchingListInModeWithFilter + 65
34  AppKit                              0x00007fff8aa5624e _DPSNextEvent + 1434
35  AppKit                              0x00007fff8aa5589b -[NSApplication nextEventMatchingMask:untilDate:inMode:dequeue:] + 122
36  AppKit                              0x00007fff8aa4999c -[NSApplication run] + 553
37  AppKit                              0x00007fff8aa34783 NSApplicationMain + 940
38  Mac Linux USB Loader                0x000000010001c432 main + 34
39  libdyld.dylib                       0x00007fff83b445fd start + 1
)

我已经尝试过我所想过的一切,但是,我在Objective-C上基本上是自学成才,我担心我可能会遗漏一些东西。如果您需要任何其他源代码,请随时询问。

3 个答案:

答案 0 :(得分:1)

您正在cellForRowAtIndexPath中引用您的usbArray来填充单元格,并且您将SBUSBDevice指针直接粘贴到某处的单元格显示结构中。可能你打算使用SBUSBDevice对象的一些属性(例如,NSString)。

答案 1 :(得分:0)

我想我明白发生了什么。

您发送给usbDictionary的复制邮件会向每个内容发送一条复制邮件(这对于几乎所有收集项都是典型的)。

因此,复制消息被发送到SBUSBDevice对象(存储在字典中),从而导致异常。

看看附带的代码片段,我想不出我们为什么在这里复制的原因。将对象添加到集合应该会自动增加保留计数。

答案 2 :(得分:0)

我相对肯定是这一行:

self.usbDictionary = [[(SBAppDelegate *)[NSApp delegate] usbDictionary] copy];

如果您尝试复制包含未实现复制协议的对象的字典,则会崩溃。你确定崩溃发生在你认为它发生的地方,而不是在这条线上吗?

Reference Documentation for the NSCopying Protocol

相关问题