1

I've created a custom class which conforms to NSCopying and NSMutableCopying.

I've added an implementation for -copyWithZone: and -mutableCopyWithZone:, but whenever I call -mutableCopy on my object and try to call another method, it crashes because some of the ivars have become immutable, even though I call -mutableCopyWithZone: on the ivars.

Here's how I'm copying my class:

MyObject *flipped = [list mutableCopy];
[MyObject flip:flipped];

(the code fails on +flip:, because it tries to use removeObjectAtIndex: and addObject: on a NSMutableArray ivar)

Here's how I'm copying the class:

- (id)mutableCopyWithZone:(NSZone *)zone {

    id instance = nil;

    if ((instance = [[[self class] alloc] init])) {

        [instance setArray:[self.array mutableCopyWithZone:zone]];
        [instance setObjects:[self.objects mutableCopyWithZone:zone]];

        [instance setItemCount:self.itemCount];

    }

    return instance;

}

I'm not sure why it's failing, but I really don't understand why it isn't making array and objects mutable.

Any help appreciated.

Jack Greenhill
  • 10,240
  • 12
  • 38
  • 70
  • 1
    "the code fails on +flip:, because it tries to use removeObjectAtIndex: and addObject: on a NSMutableArray ivar" - is it really an `NSMutableArray`? –  Feb 12 '13 at 20:24
  • Do you have the array or objects properties declared as `copy`? – Jesse Rusak Feb 12 '13 at 20:25
  • It's not an NSMutableArray at runtime, it is an __NSArrayI, but it's defined as an NSMutableArray in the code. – Jack Greenhill Feb 12 '13 at 20:26
  • @JackGreenhill And how the `setArray:` method is defined (i. e. implemented)? –  Feb 12 '13 at 20:26

1 Answers1

3

My last idea: if the setArray: and setObjects: methods are actually setters for properties declared as @property (copy), then they'll copy the arrays passed in - and copy always returns an immutable object. In this case, the easy way to fix this would be declaring them as (retain) instead of (copy).

  • 2
    Considering this is inside a `copy`, I suggest setting the ivars of the new instance directly instead of using the set accessor. – Steven Fisher Feb 12 '13 at 20:48
  • @StevenFisher The problem lies way below this: mutable objects should not be used as properties. –  Feb 12 '13 at 20:51
  • Agreed. I made an assumption, probably unwarranted, that properties were being used here for memory management purposes only. – Steven Fisher Feb 12 '13 at 20:54
  • @StevenFisher And that would be fine, IMHO. Still in an immutable way only, though. –  Feb 12 '13 at 20:55