2011-02-04 1 views
0

Я не могу получить доступ к переменным-членам подкласса после отправки объекта в качестве суперкласса. Функции членов работают. Смотрите этот пример:Не удается получить доступ к элементам подкласса после отправки в качестве суперкласса

определение супер класс

@interface SuperClass : NSObject { 
NSString *stringSuper; 
NSInteger intSuper; 
} 
- (void)test; // NSLog(@"test: SuperClass"); 

получено определение класса

@interface DerivedClass : SuperClass { 
NSString *stringDerived; 
NSInteger intDerived; 
} 
- (void)test; // NSLog(@"test: DerivedClass"); 
- (void)test1; // NSLog(@"test1: DerivedClass"); 

создать объект DerivedClass и отправить в SuperClass

DerivedClass *d = [[DerivedClass alloc] init]; 
d.stringSuper = anotherString; 
d.intSuper = anotherInt; 
d.stringDerived = anotherString1; 
d.intDerived = anotherInt1; 

[anObject sendMessage:d]; 

пытаются членам доступа после броска к DerivedClass

- (void)sendMessage:(SuperClass *)s { 
DerivedClass *d = (DerivedClass *)s; 
NSLog(@"%@", d.stringSuper); // ok 
NSLog(@"%d", d.intSuper); // ok 
NSLog(@"%@", d.stringDerived); // EXC_BAD_ACCESS 
NSLog(@"%d", d.intDerived); // ok 

[d test]; // ok ("test DerivedClass") 
[d test1]; // ok ("test1 DerivedClass") 
} 

Я объявил @properties (nonatomic, assign) для всех членов. Отладчик показывает мне правильный адрес для stringDerived, но это «вне сферы действия».

Кто-нибудь знает, в чем причина такого поведения?

Спасибо, Rodo

+0

введите код, в котором вы инициализируете переменную anotherString1, – Robin

+0

Если вы измените свойства на (неатомные, сохраняйте), произойдет ли сбой? – fbrereto

+0

@robin Спасибо за ваш ответ. Все строки инициализируются одинаково ([NSString stringWithFormat: @ "..."]). Они исходят от обратного вызова делегата. – user602313

ответ

1

Да: вы нарушили правило 1 из how to do properties. Ясно, что anotherString1 был выпущен до того момента, когда вы читаете d.stringDerived; он может быть даже недействительным в момент, когда вы установили d.stringDerived. Равным образом, anotherString, очевидно, является либо постоянной строкой, либо сохраняется чем-то другим. Было бы более очевидно, если бы вы показали свой фактический код.

Если вы определяете класс с свойством типа объекта, вы должны организовать экземпляры вашего класса для копирования или сохранения значения, присвоенного этому свойству, чтобы быть уверенным, что оно все равно будет присутствовать при следующем просмотре. Если вы используете назначение, значение, вероятно, станет недействительным очень быстро, так как оно, вероятно, будет автореализованным значением. В общем случае, если тип свойства соответствует протоколу NSCopying, и он изменен или имеет изменяемый подкласс (например: NSString, NSData, NSSet, NSArray и т. Д.), Лучше всего использовать копию, чтобы значение не менялось один раз задавать; в других случаях хорошо использовать удержание.

Сделав это, вы также должны убедиться, что память, используемая значением свойства, правильно учитывается, когда объект освобождается. Задайте значение любых свойств типа объекта равным нулю в вашей процедуре dealloc.

+0

Большое спасибо - я попытался использовать copy/keep для свойств, но я всегда использовал [NSString stringWithFormat:] вместо [[NSString alloc] initWithFormat:] для инициализации строк. Теперь это работает - еще раз спасибо! – user602313

+0

stringWithFormat: возвращает сохраненную и автореализованную строку - сохранить количество 1, которое скоро станет 0; alloc/initWithFormat: возвращает сохраненную строку, не поддерживаемую автореализацией, - сохранить счетчик 1, который останется 1 до явного выхода. Используйте Build and Analyze, чтобы помочь вам проверить, что ваш сохранить/освободить разумно во время компиляции и запустить с помощью инструмента «Утечки», чтобы проверить его во время выполнения. –