此代码有效:
monkey.h
@interface monkey : NSObject {
NSNumber *monkeyRanch;
}
@property (nonatomic, retain) NSNumber *monkeyRanch;
-(id) gatherTheMonkeys:(int)howmany;
monkey.m
@synthesize monkeyRanch;
-(id) gatherTheMonkeys:(int)howmany{
NSNumber *temp=[[NSNumber alloc] initWithInt:howmany];
monkeyRanch = temp;
[temp release];
return [monkeyRanch autorelease];
}
appDelegate.m
theMonkeys = [[monkey alloc] gatherTheMonkeys:3];
[window addSubview:[navigationController view]];
[window makeKeyAndVisible];
..和theMonkeys
以dealloc发布。仪器没有泄漏。
但是,如果我使用NSMutable
数组而不是NSNumber
尝试相同的操作:
monkey.h
@interface monkey : NSObject {
NSMutableArray *monkeyRanch;
}
@property (nonatomic, retain) NSMutableArray *monkeyRanch;
-(id) initTheMonkeys:(int)howmany;
monkey.m @synthesize monkeyRanch;
-(id) initTheMonkeys:(int)howmany{
monkeyRanch=[[NSMutableArray alloc] init];
NSNumber *imp =[[NSNumber alloc] initWithInteger:howmany];
[monkeyRanch addObject:imp];
[imp release];
return [monkeyRanch autorelease];
}
的appDelegate
theMonkeys = [[monkey alloc] initTheMonkeys:3];
[theMonkeys retain];
这会在应用程序开始时导致(对象'monkey')的泄漏。
我尝试将initTheMonkeys
更改为以下内容:
NSMutableArray *temp=[[NSMutableArray alloc] init];
monkeyRanch=temp;
[temp release];
NSNumber *imp =[[NSNumber alloc] initWithInteger:howmany];
[monkeyRanch addObject:imp];
[imp release];
return [monkeyRanch autorelease];
但是monkeyRanch
的保留计数在释放临时值时变为零,应用程序很快就崩溃了。
我做错了什么,我该如何解决?
答案 0 :(得分:3)
你的记忆问题归结为所有权问题。当一个类有一个实例变量(例如monkeyRanch
)时,通常会在该类的初始值设定项中创建一个实例,然后在dealloc
中释放它,如下所示:
@interface Monkey : NSObject {
NSMutableArray * monkeyRanch;
}
@end
@implementation Monkey
- (id)init {
if ((self = [super init]) == nil) { return nil; }
monkeyRanch = [[NSMutableArray alloc] initWithCapacity:0];
return self;
}
- (void)dealloc {
[monkeyRanch release];
}
@end
在这种情况下,Monkey
类拥有monkeyRanch
成员。
在函数调用中,您必须确保release
init
,retain
或copy
的所有本地对象。看起来你有这个部分是正确的,但我会展示一个快速的例子:
- (void)someFunction {
NSNumber * myNumber = [[NSNumber alloc] init];
...
[myNumber release];
}
接下来要理解的是,简单地设置成员变量和设置属性值之间存在巨大的差异。也就是说:
NSMutableArray * temp = [[NSMutableArray alloc] initWithCapacity:0];
monkeyRanch = temp;
[temp release]; // it's gone!
与不相同:
NSMutableArray * temp = [[NSMutableArray alloc] initWithCapacity:0];
self.monkeyRanch = temp; // now owned by self
[temp release];
在第一种情况下,您只需将指针(monkeyRanch)设置为等于另一个指针(temp)。该值不会被保留或复制。
在第二种情况下,您实际上是在设置属性。这意味着,假设该属性设置为retain,则该数组现在由您的类对象拥有。
<强> P.S:强>
你可能也会在设计方面走错路。在我看来,猴子牧场里面有许多猴子。如果这是真的,那么你的Monkey
对象真的不应该拥有MonkeyRanch。我会改用这样的东西:
<强> Monkey.h 强>
@class MonkeyRanch;
@interface Monkey : NSObject {
MonkeyRanch * ranch;
}
@property (nonatomic, assign) MonkeyRanch * ranch;
@end
Monkey.m
@implementation Monkey
@synthesize ranch;
@end
MonkeyRanch.h
#import "Monkey.h"
@interface MonkeyRanch : NSObject {
NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
MonkeyRanch.m
@implementation MonkeyRanch
@synthesize monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany {
if ((self = [super init]) == nil) { return nil; }
monkeys = [[NSMutableArray alloc] initWithCapacity:howMany];
for (int index = 0; index < howMany; index++) {
Monkey * newMonkey = [[Monkey alloc] init];
[newMonkey setRanch:self];
[monkeys addObject:newMonkey];
[newMonkey release];
}
return self;
}
- (void)dealloc {
[monkeys release];
}
@end
用法:
#import "MonkeyRanch.h"
MonkeyRanch * theRanch = [[MonkeyRanch alloc] initWithNumberOfMonkeys:3];
...
[theRanch release];
答案 1 :(得分:1)
确实,你错过了这个:
theMonkeys = [[monkey alloc] initTheMonkeys:3];
[theMonkeys retain];
当你'''某事时,你最终会得到一个隐含的“保留”(保留计数为1)。有你的泄漏;你们都是在开始和保留它。