这只是一个帮助我学习Objective-C的测试,它使用NSMutableArray将轮胎对象添加到汽车对象中的实例变量中:
// INTERFACE
@interface CarBody : NSObject {
NSMutableArray *tires;
}
// Should this be (id *) it works but I was convinced it would be pointer?
- (void) addTire:(id)newTire;
@end
@interface TireSnow : NSObject {
}
@end
// IMPLEMENTATION
@implementation CarBody
- (void) addTire:(id)newTire {
[tires addObject:newTire];
// ** Release here or in main()?
}
- (id) init {
[super init];
tires = [[NSMutableArray alloc] init];
NSLog(@"_init: %@", NSStringFromClass([self class]));
return self;
}
- (void) dealloc {
NSLog(@"_deal: %@", NSStringFromClass([self class]));
[tires release];
[super dealloc];
}
@end
我确实有几个问题......
提前感谢任何帮助...
加里
我正在阅读内存管理规则,但它们确实需要一些时间来吸收并确实需要一定程度的理解,这在开始时很难获得。我在这种情况下想知道的是我将在哪里发布我在main中分配的newSnowTire。当我将它添加到setter中的数组时,会在数组中创建一个新对象(这是我的理解)所以我的想法是我需要释放我从alloc获得的实例?
// MAIN
#import <Foundation/Foundation.h>
int main (int argc, const char * argv[]) {
NSAutoreleasePool * pool = [[NSAutoreleasePool alloc] init];
CarBody *newCarBody_001;
TireSnow *newSnowTire_001;
newCarBody_001 = [[CarBody alloc] init];
newSnowTire_001 = [[TireSnow alloc] init];
[newCarBody_001 addTire:newSnowTire_001];
// Clean up
[newCarBody_001 release];
[newSnowTire_001 release];
[pool drain];
return 0;
}
刚刚添加代码以生成所有4个轮胎,轮胎释放在调用setter后移入循环中。
// CREATE TIRES
for(int loopCounter=0; loopCounter<4; loopCounter++) {
newSnowTire_001 = [[TireSnow alloc] init];
[newCarBody_001 addTire:newSnowTire_001];
[newSnowTire_001 release];
}
我刚检查过这个,这是正确的......
答案 0 :(得分:2)
(id)
或(TireSnow*)
类似,我在开始时也理解这一点。所以基本上一个对象是一个指针类型(种类),但id
已经是一个指针,因此你不需要*
。
在main
中。释放应该与alloc / retain / copy在同一个地方发生。
似乎对我好。
您可以使用[[NSMutableArray alloc] initWithCapacity:4]
。这只是对数组的提示,如果您插入更多项目,它将自动展开。在[tires length]
方法中查看addTire
。
您的-init
看起来应该更像这样:
-(id)init
{
if (self = [super init]) {
// init here
}
return self;
}
如果init-chain中出现问题,则允许self为nil
。
答案 1 :(得分:1)
您应该使用id
(不是id*
)。 Objective-C没有像对象那样的根对象概念,其中java.lang.Object
是任何和所有类的根类。 Cocoa添加了两个名为NSObject
的根类(没有超类的类),并且不常见NSProxy
。 id
是指向任何对象的指针,无论超类如何。
遗憾的是,id
和Class
被定义为指针,这意味着它们是您在定义引用时不应添加'*'
字符的唯一位置。过去遗留下来的遗憾。
在main中发布时,您应该始终在您创建或保留它们的同一范围内释放对象。 addTire:
方法就是上帝的例子,永远不会释放作为参数传递给你的对象。仅发布作为结果传递给您的对象(即使只是来自alloc
,new
和copy
方法)。
实例变量tires
的分配和发布是一个教科书示例,说明应该在哪里完成。我会扩展init
以检查超类结果,因为这虽然(永远不会信任超级总是工作,甚至返回相同的实例):
- (id) init { self = [super init]; if (self) { tires = [[NSMutableArray alloc] init]; NSLog(@"_init: %@", NSStringFromClass([self class])); } return self; }
NSArray
。最好的方法可能是用init
方法要求轮胎。如果这不可能,那么使用NSArray
而不是NSMutableArray
就无法获得任何好处。答案 2 :(得分:0)
类型id
的定义如下(在objc.h中):
typedef struct objc_object {
Class isa;
} *id;
所以id
已经是指向对象的指针。 id*
将是指向指针的指针。
至于你应该释放轮胎的位置 - 你发布的代码中没有任何内容表明需要释放它。该物件从未声称拥有轮胎,因此无需释放轮胎。如果某些内容声称您的代码中的其他地方拥有轮胎所有权,则该对象有责任在完成后释放其声明。
the Objective-C memory management rules中对此进行了解释。它很短,必读。