热门标签 | HotTags
当前位置:  开发笔记 > 编程语言 > 正文

可接受的释放属性的方式-Acceptablewaystoreleaseaproperty

Assumethereisaclasswiththefollowinginterface:假设有一个类具有以下接口:#import<FoundationFoundati

Assume there is a class with the following interface:

假设有一个类具有以下接口:

#import 

@interface MyClass : NSObject {

}
@property (nonatomic, retain) NSDate* myDate;

-(void)foo;

@end

and the following implementation:

和下面的实现:

#import "MyClass.h"


@implementation MyClass
@synthesize myDate = _myDate;

- (void)dealloc
{
    [_myDate release];
    [super dealloc];
}

-(void)foo
{
    NSDate* temp = [[NSDate alloc] init];
    self.myDate = temp;
    [temp release];
}

@end

1) In the function foo will releasing like this ensure that the retain count of the objects is properly maintained (i.e. no memory is leaked and no unnecessary releases are performed).

1)在函数foo中会释放这样的功能,确保保留的对象被正确地维护(即没有内存泄漏,也不会执行不必要的释放)。

    NSDate* temp = [[NSDate alloc] init];
    self.myDate = temp;
    [temp release];

2) Same question as in 1) except applied to the following technique:

2)与1)中的问题相同,但适用于以下技术:

self.myDate = [[NSDate alloc] init];
[self.myDate release]

3) Same question as in 1) except applied to the following technique:

3)除适用于以下技术外,同样的问题:

self.myDate = [[NSDate alloc] init] autorelease];

4) Same question as 1) but applied to the following technique:

(4)同样的问题,但适用于以下技术:

self.myDate = [[NSDate alloc] init];
[_myDate release]

5) Same question as 1) but applied to the following technique:

5)与1)相同的问题,但适用于以下技术:

[_myDate release];
_myDate = [[NSDate alloc] init];

4 个解决方案

#1


7  

1) Just fine.

1)很好。

2) Possibly unsafe, and will trigger warnings in the latest LLVM static analyzer. This is because the object returned by the getter method may not be the same one you passed to the setter. (The setter may have made a copy, for example, or may have failed validation and set a nil instead.) This would mean you were leaking the original object and over-releasing the one the getter gave back to you.

2)可能不安全,并在最新的LLVM静态分析器中触发警告。这是因为getter方法返回的对象可能与传递给setter的对象不同。(例如,setter可能复制了一个副本,或者可能验证失败并设置了nil。)这意味着您泄漏了原始对象,并过度释放了getter返回给您的对象。

3) Just fine; similar to 1 but the release will come when the current autorelease pool is drained instead of immediately.

3)很好;类似于1,但是释放将在当前的自动释放池被排干而不是立即释放时到来。

4) Possibly unsafe, but will not trigger warnings that I've seen. The issue is similar to the one described in 2; the object in the ivar may not be the one you passed to the setter.

4)可能不安全,但不会引发我所见过的警告。这个问题与2中描述的相似;ivar中的对象可能不是您传递给setter的对象。

5) Safe, but will not use the setter method or notify any observers of the property.

5)安全,但不会使用setter方法或通知任何观察者该属性。

In the case where the property is a retain type, and both the getter and setter are just the synthesized versions, all of the above examples will work. However, they don't all represent best practice, and may trigger analysis warnings. The goal should be that the -foo method works correctly regardless of how myDate is managing its memory. Some of your examples above don't do that.

在属性为retain类型的情况下,getter和setter都只是合成的版本,上面的所有示例都可以工作。然而,它们并不都代表最佳实践,并可能触发分析警告。目标应该是-foo方法正确工作,而不管myDate如何管理它的内存。上面的一些例子没有做到这一点。

If, for example, you decided to change the property to copy later, you should not be required to change any other code to make it work correctly. In cases 2 and 4, you would be required to change additional code because the foo method is assuming that the setter will always succeed and always set the original object.

例如,如果您决定稍后将属性更改为copy,则不应要求您更改任何其他代码以使其正确工作。在第2和第4种情况下,您需要更改其他代码,因为foo方法假定setter总是成功的,并且始终设置原始对象。

#2


3  

5) is a bug - it leaks the old instance as it doesn't get released but just reassigned.

5)是一个bug——它会泄露旧实例,因为它不会被释放,而是重新分配。

1) is clean and the best way to go. 4) is ok but puts some burden on the memory system - the object might live longer than needed. 2) technically ok, but you shouldn't directly retain/release the property - that's what the syntactic sugar is for! 3) technically ok, but also bypasses the property and relies on implementation details.

1)干净,是最好的方法。4)可以,但会给内存系统增加一些负担——对象可能会比需要的寿命长。2)技术上可以,但不能直接保留/释放属性——这就是语法糖的用途!3)技术上还可以,但也可以绕过属性并依赖于实现细节。

2) and 3) are discouraged and ask for trouble in the future when some part of code changes.

2)和3)当代码的某些部分发生变化时,会被劝阻,并在将来引起麻烦。

Edit: New code doesn't leak in 5). It has the same downsides, though.

编辑:新代码不会泄漏5),但是它也有同样的缺点。

There's a reason why we got support for properties, and it does a great and consistent use. You should only consider bypassing them if your time profile gives very clear hints that this is a bottle neck (unlikely).

我们获得对属性的支持是有原因的,而且它的使用也很好。只有当你的时间档案清楚地表明这是一个瓶颈(不太可能)时,你才应该考虑绕过它们。

#3


2  

First, if you want to avoid the alloc, release, autorelease etc... you can call a date factory method which doesn't start with alloc.

首先,如果你想避免alloc, release, autorelease等…您可以调用date factory方法,它不以alloc开头。

For example: self.myDate = [NSDate date];

例如:自我。替换=(NSDate日期);

The date class factory method does an autorelease according to the convention rules. Then the property retains it.

date类factory方法根据约定规则执行自动发送。然后财产就保留了。

  1. Alloc will give it a retain count of 1, then assigning the property will retain it. Since your class is now retaining it from the property, you can release it to counter act the alloc.

    Alloc会给它一个1的retain count,然后分配属性会保留它。由于您的类现在从属性中保留它,所以您可以释放它来对抗alloc。

  2. Ditto but that's a wierd round about way to do it.

    我也这么认为,但这是一种更明智的做法。

  3. 3 is equivalent to the code I had above ([NSDate date]);

    3等于我上面的代码([NSDate]);

  4. In this case, the property will retain it (after alloc incremented the retain count), then you're going under the covers to decrement it. Works but I wouldn't recommend doing that since you're synthesized (retain) property will do that for you.

    在这种情况下,属性将保留它(在alloc增加retain count之后),然后您将在覆盖下对它进行递减。这是可行的,但我不建议这样做,因为你是合成的(保留)属性会为你做到这一点。

#4


-1  

the pattern of release and renew is merely a semantic. You get a retain count for each of the following.

释放和更新的模式仅仅是语义上的。您将获得以下每一个保留计数。

myObject = [Object alloc]
objectCopy = [myObject copy]
myNewObject = [Object newObjectWithSomeProperties:@"Properties"] // Keyword here being new
// And of course
[myObject retain]

a property with the modifier (retain) or (copy) will have retain count on it. the backing store _myDate is merely where the object is actually stored.

带有修饰符(保留)或(复制)的属性将保留该属性。支持存储区_myDate仅仅是对象实际存储的地方。

when you get a retain count you need to release. Either immediately with the [myObject release] message or let the pool release it with [myObject autorelease]

当你得到一个保留计数,你需要释放。要么立即使用[myObject release]消息,要么让池使用[myObject autorelease]释放它

Whatever the case, Any retain you are given (implicit or explicit) will need to be released. Otherewise the garbage collector will not collect your object and you will have a memory leak.

无论如何,你得到的任何保留(隐式或显式)都需要被释放。此时垃圾收集器将不会收集您的对象,您将会有内存泄漏。

the most common usage in

最常见的用法

Object myObject = [[[Object alloc] init] autorelease]; // Use this when you dont plan to keep the object.

Object myObject = [[Object alloc] init];
self.myProperty = [myObject autorelease]; // Exactally the same as the Previous. With autorelease
                                         // Defined on the assignment line.

self.myProperty = [[[Object alloc] init] autorelease]; // Same as the last two. On one line.

I will demonstrate other possibilities

我将展示其他可能性。

// Uncommon. Not incorrect. But Bad practice
myObject = [[Object alloc] init];
self.myProperty = myObject;

// Options
[_myProperty release] // Bad practice to release the instance variable
[self.myProperty release] // Better practice to Release the Property;

// releasing the property or the instance variable may not work either.
// If your property is using the (copy) modifier. The property is copied rather then retained.
// You are still given a retain count.
// But calling release on a copy will not release the original

[myObject release]; // Best Practice. Good when Threading may run the autorelease pool
[myObject autorelease]; // As good as the previous. 
                        // But may leave your object in memory during long operations

Essentially, your object given a retain will be the same object in the Property the Variable and the Instance Variable. Releasing on any of them will release it. However. Best practice says that if you retain an object. Best to call release on the same variable of that object. Even if Autorelease and retain is called on the other side.

本质上,给定retain的对象将是属性中的相同对象变量和实例变量。释放它们中的任何一个都会释放它。然而。最佳实践是,如果你保留一个对象。最好对该对象的相同变量调用release。即使在另一边调用Autorelease和retain。

// Other items that give you a retain count. Core Media or Core Anything Functions that have Create Or Copy in the name.

//其他能给你留数的项目。核心媒体或任何在名称中创建或复制的功能。


推荐阅读
author-avatar
vfjgjgv
这个家伙很懒,什么也没留下!
PHP1.CN | 中国最专业的PHP中文社区 | DevBox开发工具箱 | json解析格式化 |PHP资讯 | PHP教程 | 数据库技术 | 服务器技术 | 前端开发技术 | PHP框架 | 开发工具 | 在线工具
Copyright © 1998 - 2020 PHP1.CN. All Rights Reserved | 京公网安备 11010802041100号 | 京ICP备19059560号-4 | PHP1.CN 第一PHP社区 版权所有