阵列通过Setter?

时间:2009-09-23 09:34:05

标签: objective-c

这只是一个帮助我学习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

我确实有几个问题......

  1. 在addTire方法中,(id)是正确的,我认为它会是(id *)
  2. 释放我要添加到数组中的项目,我应该在setter内部还是在main()之后调用它?
  3. 我是否在正确的位置分配/释放NSMutableArray(轮胎),感觉如此?
  4. 有没有办法用NSArray做这个(因为我只想要4个轮胎),我确实试过这个但是混淆了试图分配数组并定义它的大小。
  5. 提前感谢任何帮助...

    加里

    编辑:

    我正在阅读内存管理规则,但它们确实需要一些时间来吸收并确实需要一定程度的理解,这在开始时很难获得。我在这种情况下想知道的是我将在哪里发布我在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;
    }
    

    EDIT_002:

    刚刚添加代码以生成所有4个轮胎,轮胎释放在调用setter后移入循环中。

    // CREATE TIRES
    for(int loopCounter=0; loopCounter<4; loopCounter++) {
        newSnowTire_001 = [[TireSnow alloc] init];
        [newCarBody_001 addTire:newSnowTire_001];
        [newSnowTire_001 release];
    }
    

    我刚检查过这个,这是正确的......

    1. NewSnowTire_001(alloc)RetainCount = 1
    2. NewSnowTire_001(addTire)RetainCount = 2
    3. NewSnowTire_001(release)RetainCount = 1
    4. NewSnowTire_001最后由dealloc方法发布。

3 个答案:

答案 0 :(得分:2)

  1. (id)(TireSnow*)类似,我在开始时也理解这一点。所以基本上一个对象是一个指针类型(种类),但id已经是一个指针,因此你不需要*

  2. main中。释放应该与alloc / retain / copy在同一个地方发生。

  3. 似乎对我好。

  4. 您可以使用[[NSMutableArray alloc] initWithCapacity:4]。这只是对数组的提示,如果您插入更多项目,它将自动展开。在[tires length]方法中查看addTire


  5. 您的-init看起来应该更像这样:

    -(id)init
    {
        if (self = [super init]) {
            // init here
        }
        return self;
    }
    

    如果init-chain中出现问题,则允许self为nil

答案 1 :(得分:1)

  1. 您应该使用id (不是id*。 Objective-C没有像对象那样的根对象概念,其中java.lang.Object是任何和所有类的根类。 Cocoa添加了两个名为NSObject的根类(没有超类的类),并且不常见NSProxyid是指向任何对象的指针,无论超类如何。 遗憾的是,idClass被定义为指针,这意味着它们是您在定义引用时不应添加'*'字符的唯一位置。过去遗留下来的遗憾。

  2. 在main中发布时,您应该始终在您创建或保留它们的同一范围内释放对象。 addTire:方法就是上帝的例子,永远不会释放作为参数传递给你的对象。仅发布作为结果传递给您的对象(即使只是来自allocnewcopy方法)

  3. 实例变量tires的分配和发布是一个教科书示例,说明应该在哪里完成。我会扩展init以检查超类结果,因为这虽然(永远不会信任超级总是工作,甚至返回相同的实例)

  4. - (id) init {
        self = [super init];
        if (self) {
          tires = [[NSMutableArray alloc] init];
          NSLog(@"_init: %@", NSStringFromClass([self class]));
        }
        return self;
      }
    
    1. 如果您从一开始就可以使用所有四个轮胎,则可以使用NSArray。最好的方法可能是用init方法要求轮胎。如果这不可能,那么使用NSArray而不是NSMutableArray就无法获得任何好处。

答案 2 :(得分:0)

类型id的定义如下(在objc.h中):

typedef struct objc_object {
    Class isa;
} *id;

所以id已经是指向对象的指针。 id*将是指向指针的指针。

至于你应该释放轮胎的位置 - 你发布的代码中没有任何内容表明需要释放它。该物件从未声称拥有轮胎,因此无需释放轮胎。如果某些内容声称您的代码中的其他地方拥有轮胎所有权,则该对象有责任在完成后释放其声明。

the Objective-C memory management rules中对此进行了解释。它很短,必读。