【问题标题】:Array Via Setter?数组通过设置器?
【发布时间】:2009-09-23 09:34:04
【问题描述】:

这只是一个帮助我学习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 个轮胎),我确实尝试过,但在尝试分配数组并定义其大小时搞混了。

提前感谢您的帮助...

加里

编辑:

我正在阅读内存管理规则,但它们确实需要一些时间来吸收,并且确实需要一定程度的理解,这在开始时很难获得。在这种情况下,我想知道我将在哪里释放我在 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(发布)RetainCount = 1
  4. NewSnowTire_001 最终通过 dealloc 方法释放。

【问题讨论】:

    标签: objective-c


    【解决方案1】:
    1. (id)(TireSnow*) 是类似的,我一开始也很难理解。所以基本上一个对象是指针类型(种类),但id已经是一个指针,所以你不需要在它后面加上*

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

    3. 我觉得没问题。

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


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

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

    如果 init 链中出现问题,这允许 self 成为 nil

    【讨论】:

      【解决方案2】:
      1. 您应该使用id (而不是id*。 Objective-C 没有根对象的概念,例如 Java,其中 java.lang.Object 是任何和所有类的根类。 Cocoa 添加了两个名为NSObject 的根类(没有超类的类)和不太常见的NSProxyid 是指向任何对象的指针,与超类无关。 不幸的是,idClass 都被定义为指针,这意味着它们是唯一在定义引用时不应添加'*' 字符的地方。过去的不幸遗产。

      2. 在 main 中发布,您应该始终在您创建或保留对象的同一范围内发布对象。 addTire: 方法是一个非常好的例子,永远不要释放作为参数交给你的对象。只释放作为结果交给你的对象(即使那样也只能来自allocnewcopy方法)

      3. 实例变量tires的分配和释放是应该在哪里完成的教科书示例。我会扩展 init 以检查超类结果,因为 (永远不要相信 super 总是工作,甚至返回相同的实例)

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

      【讨论】:

        【解决方案3】:

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

        typedef struct objc_object {
            Class isa;
        } *id;
        

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

        至于您应该在哪里释放轮胎 - 您发布的代码中没有任何内容表明需要释放它。该对象从不声称拥有轮胎的所有权,因此无需释放它。如果在代码中的其他地方有东西声称拥有轮胎的所有权,那么该对象有责任在它完成时释放它的所有权。

        这在the Objective-C memory management rules 中有解释。很短,值得一读。

        【讨论】:

          猜你喜欢
          • 1970-01-01
          • 1970-01-01
          • 2014-07-01
          • 1970-01-01
          • 2012-12-08
          • 2010-12-02
          • 1970-01-01
          • 1970-01-01
          • 1970-01-01
          相关资源
          最近更新 更多