【问题标题】:Custom Object Initialization in Objective-CObjective-C 中的自定义对象初始化
【发布时间】:2011-06-28 10:19:48
【问题描述】:

我在 Objective-C 中创建了一个自定义对象。现在我想创建一个自定义初始化程序。该对象有两个属性,名称和分数。所以我的初始化程序如下:

- (id)initWithName:(NSString *)playerName {

    if ((self = [super init])) {
        self.name = [playerName retain];
        self.score = [NSNumber numberWithInt:0];
    }

    return self;
}

我在这里正确使用 retain 吗?或者我可以把它做成self.name = playerName;之类的吗?

此外,假设我想要另一个初始化程序,但将 initWithName:playerName 保留为指定的初始化程序。如何让第二个初始化程序调用第一个?

对于最后一个问题,我知道我也需要重写 - (id)init 方法。但是,我在那里做什么?如果仅使用 init 初始化类,只需分配测试属性?

谢谢!

【问题讨论】:

    标签: iphone objective-c cocoa-touch ipad


    【解决方案1】:

    我在这里正确使用了保留吗?

    不,你不是。您应该使用

    self.name = playerName;
    

    按照您的建议,或(按照 Apple 的建议)

    name = [playerName copy];
    

    不建议在-init 中使用访问器,因为子类可能会覆盖它们。

    另外,请注意,由于 NSString 实现了 NSCopying,您应该使用复制属性,而不是保留属性。

    此外,假设我想要另一个初始化程序,但将 initWithName:playerName 保留为指定的初始化程序。如何让第二个初始化程序调用第一个?

    -init 为例(因为如果您指定的初始化程序不同,您必须覆盖超类的指定初始化程序)

    -(id) init
    {
        return [self initWithName: @"Some default value"];
    }
    

    【讨论】:

    • 关于NSString 实现NSCopying,那么@property (nonatomic, retain) NSString ... 会错吗?我应该用副本代替保留吗?如果是这样,那么我不应该在dealloc 中发布它对吗?
    • @Nayefc: @property (copy) NSString* 适合 NSString 属性(nonatomic 当然是可选的)。您仍然需要在dealloc 中释放它,因为您拥有使用copy 获得的对象。
    【解决方案2】:

    如果您在 .h 类中将 name 声明为保留属性,并且在 .m 文件中也有 @synthesized,则可以保留 self.name = playerName;

    对于初始化,您可以将下面两行代码放在单独的方法中。

    -(void) initializeWithName:(NSString*) aName withNumber:(int) aNumber
    {
      self.name = aName;
      self.score = [NSNumber numberWithInt:aNumber];
    }
    

    让你拥有三种初始化方法。

    - (id)initWithName:(NSString *)playerName {
    
        if ((self = [super init])) {
          [self initializeWithName:playerName withNumber:0]
        }
    
        return self;
    }
    
    
    - (id)initWithNumber:(int*) aNumber {
    
        if ((self = [super init])) {
           [self initializeWithName:nil withNumber:aNumber]
        }
    
        return self;
    }
    
    
    - (id)init{
    
        if ((self = [super init])) {
            [self initializeWithName:nil withNumber:0]
        }
    
        return self;
    }
    

    【讨论】:

      【解决方案3】:

      对于我们这些新手来说有什么价值:

      在普通语言中,可以在实例化类时简单地定义参数:

      public final class MakeBed {
      
          private var foo:Object;
          public var bar:Array;
      
          public function MakeBed(_foo:Object, _bar:Array) {
              // Do stuff
              foo = _foo;
              bar = _bar;
          }
      
      }
      

      那么当我们要实例化类时,就这么简单:

      var myBeadMaker:MakeBed = new MakeBed({}, []);
      

      在 objc 中,一切都是逆向的。

      您可以创建类似于以下内容的自定义初始化程序:

      // These @properties go into the header.h file
      @property (nonatomic, retain) NSString *foo;
      @property (nonatomic, retain) NSString *bar;
      
      // This is in your implimentation.m file
      - (id) initWithInfo:(NSObject*)foo withBar:(NSArray *)bar {
          _foo = foo;
          _bar = bar;
      }
      

      Objc 会自动“合成”getter 和 setter,并在您执行 @property 操作时自动“盲目地”使用相同的 _name _but _with _an _underscore 创建一个新变量——这很神奇——接近于“几乎也是有帮助”的一面。

      对于非新手来说很方便,但对于新手来说却是令人难以置信的困惑——只要相信 getter 和 setter 已经完成并且 _new _var _is _available。

      还有每个人都忘记提及的关键......

      当你想用你的自定义初始化器实例化类时,你可以这样做:

      MakeBed myBedMaker = [[MakeBed alloc] initWithInfo:*foo withBar:*bar];
      

      【讨论】:

      • initWithInfo:withBar: 方法确实是错误的。它不调用 super 也不返回任何东西!
      • 您已将foobar 定义为字符串,但使用为它们分配NSObjectNSArray。 (对于具有可变子类(例如字符串和数组)的类使用保留/强也是不好的做法)
      • [[MakeBed alloc] initWithInfo:*foo withBar:*bar] 也是错误的。您将参数作为initWithInfo:foo withBar:bar 传递。所有这些都是基本的 Objective-C。
      • -1。你真的错过了语言的一些基本概念,无法与任何东西进行比较分析。
      • 顺便说一句,当你接触一门语言时,你应该首先了解它的基本结构。 "除非您另外指定,否则合成实例变量与属性同名,但带有下划线前缀。例如,对于名为 firstName 的属性,合成实例变量将称为 _firstName。"这取自 Apple 文档,非常明显。
      猜你喜欢
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2010-09-14
      • 2014-10-07
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多