简体   繁体   English

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

[英]Program crashes when adding object to array

I have an Objective-C class, SBUSBDevice , which represents a USB drive that the user has plugged into their system. 我有一个Objective-C类SBUSBDevice ,它表示用户已插入其系统的USB驱动器。 In one of my view controllers, I grab the dictionary containing these objects, add them to an array, and attempt to do things with this array: 在我的一个视图控制器中,我抓取了包含这些对象的字典,将它们添加到数组中,并尝试使用此数组来做事:

#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;
}

Unfortunately, when I run the code, it throws the following exception: 不幸的是,当我运行代码时,它抛出以下异常:

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

As far as I know, I am not trying to copy any SBUSBDevice instances, so there should be not need to even execute copyWithZone: . 据我所知,我没有尝试复制任何SBUSBDevice实例,因此甚至不必执行copyWithZone: SBUSBDevice I am using this same technique in other areas in my app, with slight differences, and they all work. 我在我的应用程序的其他区域中使用了相同的技术,但有细微差别,并且它们都可以工作。 Why is this exception being thrown? 为什么会引发此异常?

Here is how the SBUSBDevice objects are originally created. 最初是如何创建SBUSBDevice对象的。 Note that they are being put into the dictionary which is later referenced by the code above: 请注意,它们被放入字典中,随后由上面的代码引用:

- (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;
                }
            }
        }
    }
}
}

And here's the text of the exception (it occurs once for every USB drive that is plugged in): 这是该异常的文本(对于插入的每个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
)

I've tried everything that I've thought of, however, I am largely self-taught at Objective-C and I am afraid that I may be missing something. 我已经尝试过所有我想过的东西,但是,我在Objective-C方面自学成才,而且恐怕会丢失一些东西。 If you need any additional source code, please feel free to ask. 如果您需要任何其他源代码,请随时询问。

You are referencing your usbArray in cellForRowAtIndexPath to populate the cell, and you're sticking a SBUSBDevice pointer directly into the cell display structures somewhere. 您要在cellForRowAtIndexPath中引用usbArray来填充单元格,并将SBUSBDevice指针直接粘贴到某个单元格的显示结构中。 Probably you meant to use some property (eg, an NSString) of the SBUSBDevice object. 可能是您打算使用SBUSBDevice对象的某些属性(例如,NSString)。

I think I understand what is happening. 我想我知道发生了什么事。

The copy message you send to the usbDictionary sends a copy message to each of it's content (this is typical to almost all Collection items). 您发送给usbDictionary的复制消息会向其每个内容发送一个复制消息(这对于几乎所有Collection项都是典型的)。

Therefore, the copy message is sent to SBUSBDevice objects (which are stored in the dictionary) and thus, causing the exception. 因此,复制消息被发送到SBUSBDevice对象(存储在字典中),从而导致异常。

Looking at the pieces of code attached, I can't think of the reason why we're making a copy here. 看看所附的代码,我想不出为什么在这里进行复制的原因。 Adding objects to collections should automatically increase retain count. 将对象添加到集合中将自动增加保留计数。

I am relatively sure it is this line: 我相对确定是这一行:

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

If you try to copy a dictionary containing objects that do not implement the copying protocols, it will crash. 如果尝试复制包含未实现复制协议的对象的字典,则字典将崩溃。 Are you certain that the crash happens where you think it does, and not on this line? 您确定崩溃发生在您认为发生的地方,而不是在此行上吗?

Reference Documentation for the NSCopying Protocol NSCopying协议的参考文档

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM