2010-04-02 2 views
10

Возможно, мне не хватает чего-то очевидного, но я реализую NSCopying на одном из моих объектов. Этот объект имеет частные переменные экземпляра, которые не отображаются через геттеры, поскольку они не должны использоваться вне объекта.Лучшая практика для копирования частных экземпляров vars с NSCopying

В моей реализации copyWithZone: мне нужно выделить/инициализировать новый экземпляр, но также настроить его состояние для соответствия текущему экземпляру. Я, очевидно, могу получить доступ к текущему частному состоянию изнутри copyWithZone:, но я не могу установить его в новый объект, потому что для этого состояния нет аксессуаров.

Есть ли стандартный способ обойти это, сохранив при этом конфиденциальность данных?

Спасибо.

ответ

8

Во-первых, вы всегда должны иметь добытчиками, даже если они частные. Ваш объект должен иметь доступ только к своим собственным иварам с помощью аксессуаров (за исключением очень небольшого числа случаев). Это избавит вас от многих страданий от управления памятью.

Во-вторых, предложение Alex использовать -> является стандартным подходом, хотя это нарушает правило геттеров выше. Существует небольшое количество исключений из этого правила, и копия является одной из них. Использование частных разработчиков здесь по-прежнему разумно (и я использовал это исключительно так), но я нашел по разным причинам, что использование -> часто работает более чистым.

Будьте очень осторожны, чтобы правильно управлять памятью. Если вам нужно позвонить [super copyWithZone:], вам также следует ознакомиться с сложностями NSCopyObject() и тем, как это повлияет на вас, даже если вы не используете его сами. Я подробно обсудил это в "NSCopyObject() considered harmful."

+0

Благодарим за упоминание о частных аксессуарах, а также о рисках NSCopyObject. –

+0

Я не уверен, как использование readonly-аксессуаров помогает управлению памятью? Если вы не используете его с 'assign' или' keep', не имеет значения, используете ли вы getter или переменную напрямую. – Hemant

+0

@ Gemant, потому что вызывающему абоненту не нужно быть осторожным в отношении того, является ли свойство в настоящее время (или в будущем) readonly или нет. Это не дело звонящего, и со временем это может измениться, и тогда вам нужно будет выследить каждый фрагмент кода, который сделал это неправильно. Придерживаясь простых правил, ошибки становятся очевидными. Когда вы говорите «о, если только я не знаю, что это нормально, тогда вы начинаете заниматься головными болями. –

5

Вы можете получить доступ к переменным экземпляра копии напрямую. Вы используете тот же синтаксис разыменования указателя, который вы использовали бы со структурой. Так, например, если ваш класс это:

@interface MyCopyableClass : NSObject { 
    int anInstanceVariable; 
} 
@end 

Вы можете сделать это:

- (id)copyWithZone:(NSZone *)zone { 
    MyCopyableClass *theCopy = [[[self class] allocWithZone:zone] init]; 
    theCopy->anInstanceVariable = anInstanceVariable; 
    return theCopy; 
} 
1

Один из вариантов заключается в создании пользовательского инициализатора, который принимает частные значения iVar. Таким образом, вы создаете его как:

-(id) initWithPropertyOne:(SomeClass *) anObject andPropertyTwo:(SomeClass *) anotherObject; 

Когда вы создаете экземпляр копии, просто используйте пользовательский инициализатор.

Смежные вопросы