记忆管理问题

时间:2010-02-28 09:25:13

标签: objective-c cocoa class memory-management

我以为我得到了Cocoa内存管理的支持,但我还有很多需要学习的东西。

看看我写的这堂课:

Word.h

#import <UIKit/UIKit.h>


@interface Word : NSObject {
    NSString *word;
    NSMutableArray *wordArray;
}

@property (nonatomic ,retain) NSString *word;
@property (nonatomic ,retain) NSMutableArray *wordArray;

@end

Word.m

#import "Word.h"


@implementation Word

@synthesize word, wordArray;

- (void)setWord:(NSString *)aWord {
    NSMutableArray *newValue = [[NSMutableArray alloc] init];
    self.wordArray = newValue;
    [newValue release];

    for (int i = 0 ;i < [aWord length] ;i++) {
        NSString *character = [[NSString alloc] init];
        character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]];
        [wordArray addObject:character];
        //[character release];
    }
}

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

@end

正如你可以看到我在设置字符串时填充数组。我通过拉出字符串的char并将它们放入一个新分配的字符串中来填充for循环。 然后我把那个字符串放在数组中,然后我必须释放字符串。 而且我在这里做错了,因为我正在释放我投入阵列的价值。当我以后试图使用数组时,它就消失了。

我该怎么办呢?将“character”作为属性并在dealloc中释放它是错误的,因为它只是暂时的。

2 个答案:

答案 0 :(得分:6)

首先,您不需要将新的NSString分配给character,因为您会立即用另一个对象覆盖它。请记住,它是一个指针,因此当您指定它时,您不会更改它指向的对象,只会将其指向另一个对象。因此,当我们丢失指向它的指针时,您分配并最初分配给character的对象会泄露到下一行。

现在,stringWithFormat返回一个自动释放的字符串,character然后指向该字符串。您不应该发布此对象,但这是注释掉的行中发生的情况。所以循环会更好:

for (int i = 0 ;i < [aWord length] ;i++) {
        NSString* character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]];
        [wordArray addObject:character];
}

答案 1 :(得分:3)

除内存管理问题外,您是否知道已覆盖word属性的setter函数?

当你@synthesize你的word属性时,setter和getter方法是在幕后生成的,所以- (void)setWord:(NSString *)aWord;- (NSString *)word;已有函数你可以在{{{ 3}}或Objective-C primer

由于您已创建(void)setWord:(NSString *)aWord;函数,因此会覆盖生成的setter。由于您实际上没有设置word变量,因此您的属性已“损坏”。

作为一个例子,也许将其重写为:

#import "Word.h"

@implementation Word

@synthesize word, wordArray;

- (void)setWord:(NSString *)aWord {
    // set the word iVar
    if (aWord != word) {
        [aWord retain]; // I prefer [aWord copy];
        [word release];
        word = aWord;
    }

    NSMutableArray *newValue = [[NSMutableArray alloc] init];

    for (int i = 0 ;i < [aWord length] ;i++) {
        NSString *character = [NSString stringWithFormat:@"%C",[aWord characterAtIndex:i]];
        [wordArray addObject:character];

    }
    // Now that you have created the newArray, set it to the property
    self.wordArray = newValue;
    [newValue release];
}

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

@end

修改

为什么我写[aWord copy]而不是[aWord retain]?因为我会将属性声明为copy而不是retain

可变性可能是一种痛苦。我们假设不是以某种方式将NSString*传递给aWord而是传递NSMutableString*。这是可能的,因为NSMutableStringNSString的子类。我们还假设程序的另一部分改变了这个字符串的值(毕竟它是 mutable )。现在,我们已经在外部更改了Word类的属性。这破坏了封装。

@property (copy)…用于集合类是有意义的。

您可以阅读一个好的答案Programming Language documentation