Ошибка инициализации или выделения NSString?

У меня есть этот интерфейс:

 #import <Foundation/Foundation.h>
 @interface Cards : NSObject {  NSString* effect;   NSString* image;   }
-(NSString*) effect;
-(NSString*) image;
-(void) setEffect: (NSString*) effect2;
-(void) setImage: (NSString*) image2;

@end

И эта реализация:

#import "Cards.h"
@implementation Cards
-(NSString*) effect
{
    return [effect autorelease];
}
-(NSString*) image
{
    return [image autorelease];
}
-(void) setEffect: (NSString*) effect2
{
  effect = [[NSString alloc]initWithString:effect2];
}
-(void) setImage: (NSString*) image2
{
  image = [[NSString alloc]initWithString:@""];
}
-(void) dealloc
{
    [effect release];
    [image release];
    [super dealloc];
}
@end

Теперь, если я создам объект Cards, такой как Cards*, а затем запущу метод setEffect следующим образом: [card setEffect:@""]; Он компилируется, но выдает ошибку времени выполнения. Кто-нибудь знает, почему? Заранее спасибо!


person dgTheUser    schedule 02.06.2011    source источник
comment
Можете ли вы опубликовать точный код, который вы выполняете, чтобы получить ошибку, и более подробную информацию об ошибке, например, что она предоставляет в окне отладчика?   -  person Tyler    schedule 02.06.2011
comment
Кстати, вы не должны вызывать autorelease из методов получения. Основываясь на реализации вашего установщика и операции освобождения, вы владеете этими указателями, поэтому, если вы освободите их во время чтения, следующий доступ к ним может быть связан с освобожденной строкой (плохо).   -  person Tyler    schedule 02.06.2011


Ответы (2)


Я думаю, вы хотели, чтобы [image autorelease] стал [[image retain] autorelease]. В противном случае вы будете автоматически выпускать его при каждом доступе к свойству. Вы также пропускаете свои set* методы, поскольку не выпускаете старые значения перед назначением нового.

person Deepak Danduprolu    schedule 02.06.2011
comment
@user780660 user780660 В общем, вместо того, чтобы самостоятельно реализовывать методы получения, вы должны реализовать их, используя target-c @property. - person ThomasW; 02.06.2011

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

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

-(NSString *)effect {
    if (!effect) {
        effect = [[NSString alloc] init];
    }
return effect;

в вашем заголовке у вас будет

NSString *effect;

а потом имущество

@property(nonatomic, retain) NSString *effect;

то в реализации вы бы синтезировали

@synthesize effect;

и отпустите в своем -(void)dealloc

[effect release];

Таким образом, после создания класса Card вы можете вызывать такие вещи, как

card.effect = @"Whatever goes in the effect property";

//assuming card is a Card object

Надеюсь это поможет.

person Jamie    schedule 02.06.2011
comment
Эй, спасибо за помощь, но мое приложение все еще падает, если я говорю card.effect=@Something. Я не знаю, почему... - person dgTheUser; 03.06.2011