【问题标题】:NSString property and custom initNSString 属性和自定义初始化
【发布时间】:2013-10-11 09:44:27
【问题描述】:

我有 2 个问题。

First - 在 obj-c 中是否这样声明字符串

@property (nonatomic, copy) NSString *name;
@property (nonatomic, copy) NSString *city;

那些(nonatomic, copy) 是正确的还是我应该使用(nonatomic, strong) 或其他什么?

第二 - 如果我想为上述字符串设置自定义初始化程序,我是否使用

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    self = [super init];
    if (self) {
        self.name = n;
        self.city = c;
    }
}

或者我应该使用:

-(id)initWithName:(NSString *)n andCity:(NSString *)c
{
    self = [super init];
    if (self) {
        self.name = [n copy]
        self.city = [c copy];
    }
}

正如我所见,这两种方法似乎都适用于这两个问题,但我确信其中一种方法比另一种更正确,所以我想问一下我应该使用哪种方法来在以后的项目中编写正确的代码。

谢谢。

【问题讨论】:

    标签: objective-c nsstring initialization init nscopying


    【解决方案1】:

    首先 - 使用 copystrong 并不重要。我个人更喜欢复制字符串而不是保留它们

    第二个 - `

    -(id)initWithName:(NSString *)n andCity:(NSString *)c
    
       {
          self = [super init];
           if (self) {
              self.name = n;
              self.city = c;
      }
    }`
    

    您不需要再次使用copy 消息,因为您的属性将复制 n 和 c。如果你应用你的第二段代码,你将复制 n 和 c 两次并且有内存泄漏

    【讨论】:

    • 使用copystrong 非常重要。使用strong,我可以将NSMutableString 的实例传递给您,然后在事后将其从您的下方更改。这就是为什么值语义属性应该总是copy。不可变对象将通过执行return [self retain]; 来实现-copyWithZone:,以便在不需要时实际上不会创建第二个副本。
    【解决方案2】:

    您想将copy 用于值语义类型的属性。 (其中NSString 始终是一个。)否则,我可以将NSMutableString 的实例传递给您,然后在事后将其从您的下方更改。不可变对象将通过执行return [self retain] 来实现-copyWithZone:;以免在不需要时实际创建第二个副本。另见:NSString property: copy or retain?

    就您的-init 方法而言,您希望避免像您一样使用属性设置器,因为它们可能会在子类中被覆盖以执行您的类无法预料的事情。所以假设默认的 auto-ivar-synthesis 命名模式,你会想要这样做:

    -(id)initWithName:(NSString *)n andCity:(NSString *)c
    {
        if (self = [super init])
        {
            _name = [n copy];
            _city = [c copy];
        }
        return self;
    }
    

    这是一件微妙的事情,通常不会成为问题,但是如果您继续在 -init-dealloc 方法中使用固有的虚拟属性设置器,在足够长的时间线上,您 被这个烫伤了(你能说我被这个烫伤了吗?)

    至于泄露的内存,如果您使用 ARC,当 foo 是 copy 属性时执行类似 self.foo = [bar copy]; 的操作导致复制被调用两次,并且可能会生成两个副本,但 ARC 应该注意正确释放冗余/中间副本,并且应该存在内存泄漏。

    【讨论】:

      猜你喜欢
      • 1970-01-01
      • 2018-09-18
      • 1970-01-01
      • 2019-05-16
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2022-01-20
      相关资源
      最近更新 更多