views:

143

answers:

2

I am trying to copy one array to another:

NSMutableArray *itemsCopy = [[NSMutableArray alloc] initWithArray:self.items copyItems:YES];

but I get the error:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[Item copyWithZone:]: unrecognized selector sent to instance 0x5a74900'
*** Call stack at first throw:
(
    0   CoreFoundation                      0x025afc99 __exceptionPreprocess + 185
    1   libobjc.A.dylib                     0x026fd5de objc_exception_throw + 47
    2   CoreFoundation                      0x025b17ab -[NSObject(NSObject) doesNotRecognizeSelector:] + 187
    3   CoreFoundation                      0x02521496 ___forwarding___ + 966
    4   CoreFoundation                      0x02521052 _CF_forwarding_prep_0 + 50
    5   CoreFoundation                      0x025108fa -[NSObject(NSObject) copy] + 42
    6   CoreFoundation                      0x025ab732 -[NSArray initWithArray:range:copyItems:] + 290
    7   CoreFoundation                      0x02513963 -[NSArray initWithArray:copyItems:] + 99
    8   MyViewController                          0x0000787d -[MyViewController tableView:didSelectRowAtIndexPath:] + 258
    9   UIKit                               0x003968f8 -[UITableView _selectRowAtIndexPath:animated:scrollPosition:notifyDelegate:] + 1140
    10  UIKit                               0x0038d1de -[UITableView _userSelectRowAtIndexPath:] + 219
    11  Foundation                          0x000a404e __NSFireDelayedPerform + 441
    12  CoreFoundation                      0x025910c3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_TIMER_CALLBACK_FUNCTION__ + 19
    13  CoreFoundation                      0x02592704 __CFRunLoopDoTimer + 1364
    14  CoreFoundation                      0x024ef089 __CFRunLoopRun + 1817
    15  CoreFoundation                      0x024ee600 CFRunLoopRunSpecific + 208
    16  CoreFoundation                      0x024ee521 CFRunLoopRunInMode + 97
    17  GraphicsServices                    0x02db52c8 GSEventRunModal + 217
    18  GraphicsServices                    0x02db538d GSEventRun + 115
    19  UIKit                               0x00332e8f UIApplicationMain + 1160
    20  MyViewController                          0x0000210c main + 102
    21  MyViewController                          0x0000209d start + 53
)
terminate called after throwing an instance of 'NSException'
+5  A: 

You need to make sure all the contents of self.items adopt the NSCopying protocol.

If you just want a shallow copy, send the -mutableCopy message to self.items.

NSMutableArray *itemsCopy = [self.items mutableCopy];
KennyTM
Or use **copyItems:NO**
Philippe Leybaert
if I set copyItems:NO will it not copy the contents of self.items into the new array?
Sheehan Alam
@Sheehan Alam: no it won't, but if your objects don't conform to the NSCopying protocol, that won't be possible anyway.
Philippe Leybaert
Curious, what is the point of copyItems:NO if it doesn't copy the objects into the new array? In what situation would you copy an array, but not its contents?
Sheehan Alam
@Sheehan: If you pass `NO` the contents will be shared. But sometimes you just want to modify the list as a whole without touching the contents, e.g. copy a list of UIView subviews and sort it.
KennyTM
Sheeham Alam: `copyItems:YES` makes copies of the items, and initializes the new array with the copies, leaving the original items only in the original array (and wherever else they may be). With `copyItems:NO`, the new array is initialized to hold the same items as the original array.
Peter Hosey
A: 

You have to provide your classes with the copyWithZone selector (according to NSCopying protocol) if you are not copying objects that implement that protocol by default.

So if you are copying custom objects you have to implement it. The copy method always calls copyWithZone.. and you must always provide the implementation, it can't know what to copy inside objects by itself..

Jack