代码之家  ›  专栏  ›  技术社区  ›  humblePilgrim

松开指针类型属性的作用域

  •  0
  • humblePilgrim  · 技术社区  · 15 年前

    这个问题在我的代码中的许多地方都在蔓延,但通常的行为是:
    有一个视图控制器和一个详细视图控制器。我在视图控制器中创建一个自定义类的对象。这个对象包含指针类型属性,如字符串。我用这个来初始化详细视图中自定义类类型的属性,使用setter方法。 但是,当我试图在详细视图中访问这些属性时,我发现对象的指针类型属性要么显示为“超出范围”,要么其类型已更改为某种任意类型。例如,当我上次调试时,我的nsstring属性已变为CFSet或类似的类型。
    有人能提出这个问题的根本原因吗?

    1 回复  |  直到 15 年前
        1
  •  2
  •   deanWombourne    15 年前

    如果他们正在改变类型,你可能不会保留他们。

    对于字符串,您的属性应该类似于(在.h文件中)

    @property (nonatomic, copy) NSString *mString;
    

    你把它设置成

    self.mString = [NSString stringWithFormat:@"hello %@", name];
    

    它使用属性保留(或在本例中复制)字符串。

    但是,如果你这样做了

    mString = [NSString stringWithFormat:@"hello %@", name];
    

    您已在不使用属性的情况下设置了变量,因此字符串不会被保留-它将在将来的某个时间点自动删除,并且您将拥有一个不再指向字符串的指针:)


    为什么对NSStrings使用copy而不是retain?

    实际上,它是任何不可变但有可变子类(如NSDictionary、NSArray、NSSet等)的副本。

    把它当作自卫。

    如果你有这样的房产会怎么样:

    @property (nonatomic, retain) NSArray *things;
    

    在你的代码中,你使用一个循环中的东西的数量,即。

    uint max = [things count];
    for (uint n = 0; n < max; ++n) { ... }
    

    好吧,应该没问题。直到有人传入nsmutable数组而不是NSArray。您的代码假设,因为您有一个NSArray,它里面的东西的计数不会改变。

    如果有人从NSArray中删除了一个项(因为它实际上是NSMutableArray,但您不知道),而您在该循环中,您的代码将可怕地死掉(一个越界异常)。

    copy所做的不是调用retain,而是调用copy-making 100%确保在对象内部有一个不可变数组,而不是其他人传入的可变对象。可变数组可以根据需要进行更改—您有自己的副本,因此代码更安全。

    然而,这是以消耗内存为代价的——现在内存中有两个数组。通常情况下,为了避免可能发生的崩溃,需要对内存进行处理

    实际上,如果有人只是通过了一个普通的NSArray,因为它的实现是不可变的 [NSArray copy] 只不过是一个retain-so 99/100倍,通过为属性指定copy:)您不会丢失任何东西—对于所有不可变的NSxxx类也是如此。