我以为我得到了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中释放它是错误的,因为它只是暂时的。
答案 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*
。这是可能的,因为NSMutableString
是NSString
的子类。我们还假设程序的另一部分改变了这个字符串的值(毕竟它是 mutable )。现在,我们已经在外部更改了Word类的属性。这破坏了封装。
将@property (copy)…
用于集合类是有意义的。
您可以阅读一个好的答案Programming Language documentation。