Вы нарушили здесь некоторые правила, поэтому у вас все плохо. Как правило, вы не должны возвращать или принимать NSMutableDictionary
в качестве собственности. Есть исключения (и вы должны кодировать это), но обычно этого не делать. Чтобы правильно закодировать это, вам необходимо отделить свой интерфейс от своей реализации.
Правильный интерфейс:
@interface Dog: NSObject
@property (copy) NSDictionary *dict;
@end
Этот объект обещает принять и вернуть NSDictionary, и он обещает, что принятый и возвращенные словари NSDictionaries будут независимыми копиями, поэтому вызывающей стороне не нужно беспокоиться о проблемах изменчивости. Затем нам нужно реализовать эти обещания:
@implementation Dog {
NSMutableDictionary *mutableDict;
}
- (id) init
{
if ( (self = [super init]) ) {
mutableDict = [[NSMutableDictionary alloc] init];
}
return self;
}
- (void) print {
for (id key in mutableDict) {
printf("%s --> %s\n", [key UTF8String], [mutableDict[key] UTF8String] );
}
}
- (NSDictionary *)dict {
return [mutableDict copy]; // Add an -autorelease if this is MRC
}
- (void)setDict: (NSDictionary *)newValue {
// I'm going to pretend this is ARC; for MRC, code this in your style.
mutableDict = [newValue mutableCopy];
}
@end
С другой стороны, если вы действительно хотите поделиться состоянием с NSMutableDictionary, вы не должны копировать его, вы должны сохранить его, чтобы прояснить семантику.
@interface Dog: NSObject
@property (retain) NSMutableDictionary *dict;
@end
И это дает (надеюсь) понять вызывающему, что это разделяемое состояние и должно рассматриваться как таковое, и вызывающий должен делать копии, если они того пожелают. Но обычно этого следует избегать. И если вы сделаете go таким образом, я бы назвал свойство mutableDict
или что-то в этом роде, чтобы прояснить, что это необычно. Для примера см. -[NSAttributedString mutableString]
.
На самом деле нет «изменяемой, но независимой копии» semanti c в аннотациях свойств Obj C, и я бы не стал ее создавать, если у вас нет очень сильная потребность (обычно связанная с производительностью). Обычно я бы просто возвращал неизменяемую копию и позволял вызывающей стороне создать свою собственную изменяемую копию.
Еще одно примечание: иногда Какао реализует «возвращает неизменяемую копию» как «просто возвращает изменяемую копию, преобразуя ее в неизменяемую. тип." Это повышает производительность, избегая копирования за счет того, что иногда данные меняются за вашей спиной. В качестве примера посмотрите документацию для -[NSView subviews]
. На мой взгляд, вам следует избегать этого шаблона, если он не критичен для производительности (и даже в этом случае я бы сделал специальный метод, например -subviewsBackingStore
или что-то подобное, чтобы прояснить, «это странно».