将不可变对象设置为等于某事物

时间:2013-12-30 17:44:28

标签: ios objective-c automatic-ref-counting

Label有一个属性调用attributedText,

@property (nonatomic, strong) NSAttributedString *attributedText;

此属性字符串不可变。因此,要修改它,您必须制作一个可变副本。

NSMutableAttributedString *labelText= [myLabel.attributedText mutableCopy];
[labelText setAttributes:...];
myLabel.attributedText = labelText;

有人请在此过程中解释内存背后发生的事情。

myLabel.attributedText是一个指向内存中的attributionText对象的指针,该对象已经被分配和初始化。

接下来,您正在制作该对象的副本,并将* labelText设置为指向内存中的此对象。

接下来,您将使用setAttributes方法修改labelText指向的对象。

但最后一行会发生什么?我们只是将myLabel.attributedText设置为指向labelText指向内存的同一对象吗?

如果是这样,一旦整个事情超出范围,* labelText将设置为nil,但它指向的对象保留在内存中,因为myLabel.attributedText仍然指向它,保留计数为1。

ARC是否只是自动释放myLabel.attributedText最初指向的旧对象?

人们是如何在ARC之前释放该对象的?

当函数超出范围时,ARC是否总是知道将labelText指针设置为nil?

因此,当对象超出范围时保持对象活着的方法是设置一个具有强指针的属性指向该对象?当局部指针超出范围时,它们总是设置为nil吗?

编辑:我也没注意到你正在设置NSattributedString指针指向NSMutableAttributedString对象。斯坦福大学讲义有一个错字。如果您确实在代码中犯了这个错误,它仍然可以编译并运行正确吗?

1 个答案:

答案 0 :(得分:3)

由于属性是使用strong修饰符定义的,这意味着在赋值时,系统会保留指定的labelText,因此一旦方法返回,它就不会被释放。

请记住,对象是在堆上分配的,因此它们不受超出范围的方法的影响。使用ARC,可以自动为您释放未使用的对象。由于示例中的属性为strong,因此保留对象,系统不会释放它。

这适用于一个可变对象,因为NSMutableAttributedString继承自NSAttributedString(它是一个子类)。在此处阅读更多内容:Polymorphism

请务必注意,attributedText的定义与代码示例中的定义不同:

@property(nonatomic,copy) NSAttributedString *attributedText

请注意,此处的修饰符为copy而非retain

实际会发生的是,可变对象将复制到另一个实例,该实例将由标签保留,而您的可变属性字符串将在分配后立即释放。

使用

copy代替strong,以确保在设置attributedText时传递的值仍然是不可变的。