Objective c 内存管理问题

Objective c 内存管理问题,objective-c,cocoa,class,memory-management,Objective C,Cocoa,Class,Memory Management,我以为我掌握了可可记忆管理的窍门,但显然我还有很多东西要学 看看我写的这节课: Word.h #import <UIKit/UIKit.h> @interface Word : NSObject { NSString *word; NSMutableArray *wordArray; } @property (nonatomic ,retain) NSString *word; @property (nonatomic ,retain) NSMutableArr

我以为我掌握了可可记忆管理的窍门,但显然我还有很多东西要学

看看我写的这节课:

Word.h

#import <UIKit/UIKit.h>


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

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

@end
#导入
@接口字:NSObject{
NSString*字;
NSMutableArray*字数组;
}
@属性(非原子,保留)NSString*字;
@属性(非原子,保留)NSMutableArray*wordArray;
@结束

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
#导入“Word.h”
@实现字
@合成单词、单词数组;
-(void)设置字:(NSString*)aWord{
NSMutableArray*newValue=[[NSMutableArray alloc]init];
self.wordArray=newValue;
[新价值释放];
对于(int i=0;i<[aWord length];i++){
NSString*字符=[[NSString alloc]init];
character=[NSString stringWithFormat:@“%C”,[aWord characterAtIndex:i]];
[wordArray addObject:character];
//[字符释放];
}
}
-(无效)解除锁定{
[文字发布];
[wordArray发布];
[super dealoc];
}
@结束

正如您所看到的,当我设置字符串时,我正在填充一个数组。我将通过拉出字符串的char并将其放入新分配的字符串中,在for循环中对此进行修改。 然后我将该字符串放入数组中,然后我必须释放该字符串。 在这里我做错了,因为我释放了我输入到数组中的值。当我稍后尝试使用数组时,它消失了


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

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

现在,
stringWithFormat
返回一个自动释放的字符串,该字符串
字符
然后指向。这个对象不应该由您发布,但这就是注释行中发生的事情。这样循环会更好,因为:

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

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

当你合成你的word属性时,setter和getter方法是在幕后生成的,因此已经有了
-(void)setWord:(NSString*)aWord的函数
-(NSString*)字
您可以在或中阅读有关此的信息

因为您已经创建了
(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
#导入“Word.h”
@实现字
@合成单词、单词数组;
-(void)设置字:(NSString*)aWord{
//将单词设置为iVar
if(aWord!=word){
[aWord retain];//我更喜欢[aWord copy];
[文字发布];
单词=aWord;
}
NSMutableArray*newValue=[[NSMutableArray alloc]init];
对于(int i=0;i<[aWord length];i++){
NSString*character=[NSString stringWithFormat:@“%C”,[aWord characterAtIndex:i]];
[wordArray addObject:character];
}
//现在您已经创建了newArray,将其设置为属性
self.wordArray=newValue;
[新价值释放];
}
-(无效)解除锁定{
[文字发布];
[wordArray发布];
[super dealoc];
}
@结束
编辑

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

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

对集合类使用
@property(copy).
是有意义的


你可以读到一个很好的答案。

那么,当类的实例死了时,自动释放池是否会被耗尽,我是否可以保证自动释放不会过早释放我的对象?自动释放池在运行循环中释放,即在正常代码之外。它不会在你的一个方法中间触发。编辑:如果您使用后台线程,这可能是一个问题,您需要为此设置一个线程本地自动释放池。但这不是问题,说得好。不过,我不理解你的评论(“我更喜欢[抄本]”)。属性声明中说
retain
所以它应该是retain,对吗?Stephen,我扩展了我的答案。这很有趣,我从未使用过副本,因为我从未了解舒尔的功能。谢谢