Использование -mutableCopyWithZone: в пользовательском классе делает его неизменным

Я создал собственный класс, который соответствует NSCopying и NSMutableCopying.

Я добавил реализацию для -copyWithZone: и -mutableCopyWithZone:, но всякий раз, когда я вызываю -mutableCopy для своего объекта и пытаюсь вызвать другой метод, происходит сбой, потому что некоторые из иваров стали неизменяемыми, хотя я вызываю -mutableCopyWithZone: для иваров.

Вот как я копирую свой класс:

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

(код не работает на +flip:, потому что он пытается использовать removeObjectAtIndex: и addObject: на NSMutableArray ivar)

Вот как я копирую класс:

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

}

Я не уверен, почему он терпит неудачу, но я действительно не понимаю, почему он не делает array и objects изменчивыми.

Любая помощь приветствуется.


person Jack Greenhill    schedule 12.02.2013    source источник
comment
код терпит неудачу на +flip:, потому что он пытается использовать removeObjectAtIndex: и addObject: на ivar NSMutableArray - это действительно NSMutableArray?   -  person    schedule 13.02.2013
comment
У вас есть свойства массива или объектов, объявленные как copy?   -  person Jesse Rusak    schedule 13.02.2013
comment
Это не NSMutableArray во время выполнения, это __NSArrayI, но в коде он определяется как NSMutableArray.   -  person Jack Greenhill    schedule 13.02.2013
comment
@JackGreenhill А как определяется (т.е. реализуется) метод setArray:?   -  person    schedule 13.02.2013


Ответы (1)


Моя последняя идея: если методы setArray: и setObjects: на самом деле являются сеттерами для свойств, объявленных как @property (copy), то они будут копировать переданные массивы, а copy всегда возвращает неизменяемый объект. В этом случае простой способ исправить это — объявить их как (retain) вместо (copy).

person Community    schedule 12.02.2013
comment
Учитывая, что это внутри copy, я предлагаю установить ivars нового экземпляра напрямую, а не использовать метод доступа set. - person Steven Fisher; 13.02.2013
comment
@StevenFisher Проблема заключается гораздо ниже: изменяемые объекты не должны использоваться в качестве свойств. - person ; 13.02.2013
comment
Согласованный. Я сделал предположение, возможно необоснованное, что свойства использовались здесь только для целей управления памятью. - person Steven Fisher; 13.02.2013
comment
@StevenFisher И это было бы хорошо, ИМХО. Тем не менее, только неизменяемым образом. - person ; 13.02.2013