我如何管理我的iPhone';什么是记忆?

我如何管理我的iPhone';什么是记忆?,iphone,cocoa-touch,memory-management,Iphone,Cocoa Touch,Memory Management,此代码适用于: 猴子 @interface monkey : NSObject { NSNumber *monkeyRanch; } @property (nonatomic, retain) NSNumber *monkeyRanch; -(id) gatherTheMonkeys:(int)howmany; @interface monkey : NSObject { NSMutableArray *monkeyRanch; } @property (nonatomic, reta

此代码适用于:

猴子

@interface monkey : NSObject {
NSNumber *monkeyRanch;
}
@property (nonatomic, retain) NSNumber *monkeyRanch;
-(id) gatherTheMonkeys:(int)howmany;
@interface monkey : NSObject {
    NSMutableArray *monkeyRanch;
}
@property (nonatomic, retain) NSMutableArray *monkeyRanch;
-(id) initTheMonkeys:(int)howmany;
猴子

@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];
..和
按键在dealloc中释放。仪器没有泄漏。
但是,如果我尝试使用
NSMutable
数组而不是
NSNumber
执行相同操作:

猴子

@interface monkey : NSObject {
NSNumber *monkeyRanch;
}
@property (nonatomic, retain) NSNumber *monkeyRanch;
-(id) gatherTheMonkeys:(int)howmany;
@interface monkey : NSObject {
    NSMutableArray *monkeyRanch;
}
@property (nonatomic, retain) NSMutableArray *monkeyRanch;
-(id) initTheMonkeys:(int)howmany;
猴子 @合成猕猴桃

-(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];
但是随着temp的发布,monkeyRanch的保留计数变为零,应用程序很高兴地崩溃了


我做错了什么?我该如何修复它?

事实上,您没有注意到这一点:

theMonkeys = [[monkey alloc] initTheMonkeys:3];
[theMonkeys retain];

当您“初始化”某个内容时,您最终会得到一个隐式的“retain”(retain计数为1)。这是你的漏洞;你既在初始化它,又在保留它。

事实上,你错过了这一点:

theMonkeys = [[monkey alloc] initTheMonkeys:3];
[theMonkeys retain];

当您“初始化”某个内容时,您最终会得到一个隐式的“retain”(retain计数为1)。这是你的漏洞;你既在初始化它,又在保留它。

你的内存问题归结为所有权问题。当一个类有一个实例变量(例如
monkeyRanch
)时,您通常会在该类的初始值设定项中创建一个实例,然后在
dealoc
中释放它,如下所示:

@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
成员

在函数调用中,您必须确保
释放
初始化的所有本地对象
保留
复制
。看起来您的这一部分是正确的,但我仍将展示一个快速示例:

- (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
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];
MonkeyRanch.h

@implementation Monkey
@synthesize ranch;
@end
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];
MonkeyRanch.m

@implementation Monkey
@synthesize ranch;
@end
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];

你的记忆问题归结为所有权问题。当一个类有一个实例变量(例如
monkeyRanch
)时,您通常会在该类的初始值设定项中创建一个实例,然后在
dealoc
中释放它,如下所示:

@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
成员

在函数调用中,您必须确保
释放
初始化的所有本地对象
保留
复制
。看起来您的这一部分是正确的,但我仍将展示一个快速示例:

- (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
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];
MonkeyRanch.h

@implementation Monkey
@synthesize ranch;
@end
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];
MonkeyRanch.m

@implementation Monkey
@synthesize ranch;
@end
#import "Monkey.h"

@interface MonkeyRanch : NSObject {
    NSMutableArray * monkeys;
}
@property (nonatomic, retain) NSMutableArray * monkeys;
- (id)initWithNumberOfMonkeys:(int)howMany;
- (void)dealloc;
@end
@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];

如果删除了retain,则返回的autorelease对象会将Monkey拖至0 retaincount,程序…:)如果删除了retain,则返回的autorelease对象会将Monkey拖至0 retaincount,程序…:)谢谢你,詹姆斯!我缺少属性值和成员变量设置差异。我总是想返回属性,而不是类对象本身。如果我猜对了,我现在可以像theRanch.monkeys一样访问我的类属性(猴子数组)?(有什么解决办法吗?)是的,您可以通过
theRanch.monkeys
访问阵列。你现在明白了:)但说实话,我不太清楚你想做什么。也许你应该发布另一个这样的问题:“你将如何为这种数据构建一个类?”谢谢James!我缺少属性值和成员变量设置差异。我总是想返回属性,而不是类对象本身。如果我猜对了,我现在可以像theRanch.monkeys一样访问我的类属性(猴子数组)?(有什么解决办法吗?)是的,您可以通过
theRanch.monkeys
访问阵列。你现在明白了:)但说实话,我不太清楚你想做什么。也许你应该发布另一个这样的问题:“你将如何为这种数据构建一个类?”monkeyRanch到底是什么?那应该是“万能扳手”吗猴子牧场到底是什么?那应该是“万能扳手”吗