Objective c 内存管理问题
我以为我掌握了可可记忆管理的窍门,但显然我还有很多东西要学 看看我写的这节课: Word.hObjective 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
#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,我扩展了我的答案。这很有趣,我从未使用过副本,因为我从未了解舒尔的功能。谢谢