【问题标题】:Having properties that return copies of objects in the getter, and retain objects in the setter具有在 getter 中返回对象副本并在 setter 中保留对象的属性
【发布时间】:2011-01-07 18:25:23
【问题描述】:

我在理解属性时遇到了问题。 如果我希望属性不被其访问者修改(通过复制返回)并通过引用设置(保留),我应该编写什么样的属性。

例子:

MyType* theAttribute = MyObject.attribute;
[theAttribute changeSomething]; // Does not have to change the MyObject attribute, working with a copy return

MyType tmpObject = [[MyType alloc] init];
MyObject.attribute = tmpObject; // Want a retain here
[tmpObject release];

【问题讨论】:

    标签: objective-c properties copy retain


    【解决方案1】:

    在标题中将属性声明为保留:

    @property (nonatomic. retain) MyType *attribute;
    

    在实现文件中合成iVar:

    @synthesize attribute;
    

    但是提供你自己的getter,它将覆盖合成的getter:

    - (MyType)attribute {
        return [attribute copy];
    }
    

    我知道我不会自动释放返回的对象,但由于问题没有指定 iOS,所以我是从垃圾收集环境的角度来写这篇文章的。

    【讨论】:

    • 因为atomic是默认的,你还需要写setter。您不能将合成的 getter 与手动编写的 setter 混合使用,反之亦然。 (GCC 可能会让这个通过,但它是错误的。LLVM 2.0 正确地警告/错误这样的恶作剧。)
    • 谢谢,比尔。我已经修改了答案
    【解决方案2】:

    这种情况你应该自己写getter和setter。

    【讨论】:

    • setter不用自己写,getter就行了。
    • 是的,真的,我错过了。谢谢。
    • 如果你想使用atomic,你需要自己编写setter。
    【解决方案3】:

    您可能会编写自己的访问器,但具体如何取决于您是否希望自动释放复制的“get”返回:

    1. 完成“复制”的惯用方式是为访问器提供一个正常的“保留”属性,并且还支持-copy-mutableCopy 方法。后两者是语义复制对象的标准,返回的对象应该具有保留所有权。

    2. 1234563 :

    -

    - (Foo *)foo
    {
        return [[foo copy] autorelease];
    }
    

    【讨论】:

    • Uhhh... [foo copy] 不返回保留对象吗?自动释放保留的对象?
    • @Oliver:是的,[foo copy] 返回一个保留对象,但按照惯例,getter -foo 不应该,因此自动释放。产生的效果既是被调用者想要的(要返回的原始数据的副本),也是调用者所期望的(可以在没有显式释放调用的情况下删除的对象)。
    【解决方案4】:

    我建议不要通过副本返回。这会让你在内存管理中陷入困境。是自动发布的吗?不保留?问题太多了。

    相反,我建议这样做:

    MyType* attr = [MyType typeWithMyType:MyObject.attribute];
    

    什么的。

    【讨论】:

    • 如果您遵循简单的内存管理规则,则没有任何问题;方法返回自动释放的对象,您只释放分配、保留、复制或可变副本的内容。此外,这种方式要求类的使用者使用副本而不更改对象,而传递副本通过设计强制执行此操作,从而无需担心是否复制 getter 返回的值。
    • 但这就是重点。返回自动发布副本的保留属性违反了所有这些规则和命名约定。
    • 为什么? getter 不会影响作为属性存储的对象,只会返回一个副本。 副本的内存管理如何影响原件的内存管理?
    • 因为...[MyObject.myProp setVar:myVar] 不会修改 MyObject 属性的 var。它修改副本,其中 MyObject.myProp 未指定它返回副本。 [MyString stringWithString:] 你知道返回一个 autorelease'd 对象。如果您随后想将该属性链接到可编辑表等中的值,会发生什么情况?它只会影响副本。如果我错了,请纠正我,但知道你指向哪个对象是内存管理的一部分。
    • OP 特别想返回一个副本,以防止在对象控制之外对 iVar 进行更改。而内存管理的重点是你不需要知道你指向的是什么对象,只需要知道你用完后是否负责释放它。
    猜你喜欢
    • 1970-01-01
    • 2014-04-11
    • 1970-01-01
    • 2015-10-15
    • 2023-01-19
    • 1970-01-01
    • 2022-12-24
    • 2010-09-29
    • 2023-03-30
    相关资源
    最近更新 更多