为什么会导致崩溃?

时间:2011-09-02 01:04:56

标签: iphone objective-c memory

我将这两个按钮连接到这两个方法(它们几乎相同)

-(void)moveOneImageNewer{
    int num = [numberOfImage intValue];
    num--;

    numberOfImage = [[NSString stringWithFormat:@"%i",num] retain];

    //Load the image
    [self loadImage];
}

-(void)moveOneImageOlder{
    int num = [numberOfImage intValue];
    num++;
    numberOfImage = [NSString stringWithFormat:@"%i",num];

    //Load the image
    [self loadImage];
}

如果我两次击中其中任何一个(或者每次击中一次,基本上如果它们总共被调用两次),我会得到一个EXC_BAD_ACCESS。如果我抛出一个保留:numberOfImage = [[NSString stringWithFormat:@"%i",num]retain]它很好。有人可以解释为什么会这样吗?我在乐器上做了一个NSZombie并追溯到这个stringWithFormat调用。提前谢谢!

5 个答案:

答案 0 :(得分:2)

+ stringWithFormat:不包含'new','alloc','copy'或'retain',所以如果你想要它创建新的NSString,你应该期望你必须保留它的返回值坚持下去。

编辑包括这个方便的链接duskwuff亲切地挖出来:http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/mmRules.html#//apple_ref/doc/uid/20000994-BAJHFBGH

答案 1 :(得分:2)

如果numberOfImage是正确声明的属性,例如

@property (copy) NSString *numberOfImage;

并且它已正确合成(在该类的@implementation部分中):

@synthesize numberOfImage;

然后你可以这样做:

- (void) moveOneImageNewer
{
    self.numberOfImage = [NSString stringWithFormat: @"%i", [self.numberOfImage intValue] - 1];

    // Load the image
    [self loadImage];
}

属性设置器将负责保留字符串,并在必要时释放前一个字符串。

FWIW,为什么地球上的numberOfImage是字符串?为什么不是一个简单的int?

答案 2 :(得分:0)

numberOfImage是你班级的实例变量或属性,对吗?

您将其设置为stringWithFormat(返回自动释放的NSString),而不声明该对象的所有权(通过调用retain)。

如果你不保留它,它将在再次调用方法之前自动释放(然后第一行将失败,因为它试图访问先前设置的,现在自动释放的值)。

考虑使用属性,它们具有自动生成的内存管理代码(包括在设置新的NSString时释放旧的NSString)。

答案 3 :(得分:0)

好吧,如果我是对的,NSString类方法“stringWithFormat”会返回一个autorelease NSString对象。

因此,对您的方法的第二次调用会使numberOfImage指向任何内容,因为它以前指向的自动释放NSString对象已经被释放并释放,因为您没有保留它。

当你第二次调用该方法时,直接导致崩溃的部分是[numberOfImage intValue],因为你向一个不再存在的对象(由numberOfImage指向)发送消息。

答案 4 :(得分:0)

您没有在“moveOneImageOlder”中保留字符串对象,因此该对象在事件周期结束时自动释放并指向空。这就是您下次尝试使用时获得EXC_BAD_ACCESS的原因。

使用retain声明NSString的所有权。记得在你完成后发布(你可以用属性来帮助你)

-(void)moveOneImageNewer{
    int num = [numberOfImage intValue];
    num--;

[numberOfImage release];
    numberOfImage = [[NSString stringWithFormat:@"%i",num] retain];

    //Load the image
    [self loadImage];
}

-(void)moveOneImageOlder{
    int num = [numberOfImage intValue];
    num++;
[numberOfImage release];
    numberOfImage = [[NSString stringWithFormat:@"%i",num] retain];

    //Load the image
    [self loadImage];
}

在dealloc中添加:

- (void)dealloc {
    [numberOfImage release];
    [super dealloc];
}