如何使用 @synthesize 实现保留设置器?

发布于 2024-09-27 06:40:05 字数 508 浏览 4 评论 0原文

我在标题中有以下内容:

@property (nonatomic, retain) UIView *overlay;

在实现中:

@synthesize overlay;

然后:

UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

上面的 tempOverlay 变量不是不必要的吗?我不能这样做吗:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

I have the following in the header:

@property (nonatomic, retain) UIView *overlay;

And in the implementation:

@synthesize overlay;

Then:

UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

Isn't the tempOverlay variable above unnecessary? Can't I just do:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(6

葬花如无物 2024-10-04 06:40:05

合成的保留设置器如下所示:

- (void)setValue: (id)newValue
{
    if (value != newValue)
    {
        [value release];
        value = newValue;
        [value retain];
    }
}

在您的情况下,您有两种有效的方法:

1)创建一个临时变量,alloc/init(=保留),设置为属性,释放。

IView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

2)没有temp var,直接设置为ivar。

overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

更新:
如果您使用方法 2),则必须显式处理其余的内存管理(而不仅仅是保留),方法是在需要时释放之前可能具有的任何先前值。如果仅在 init 中完成一次(例如),您可以将 [overlay release]; 放入 dealloc 中。

A synthesized retained setter looks like :

- (void)setValue: (id)newValue
{
    if (value != newValue)
    {
        [value release];
        value = newValue;
        [value retain];
    }
}

In your case, you have two valid methods :

1) Create a temp var, alloc/init (= retained), set to property, release.

IView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
self.overlay = tempOverlay;
[tempOverlay release];

2) No temp var, set directly to ivar.

overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

UPDATE:
If you use method 2), you have to explicitly handle the rest of memory management (not only retaining), by releasing any previous value it might have before if needed. If done only once in init (for instance), you can just put a [overlay release]; in dealloc.

ˇ宁静的妩媚 2024-10-04 06:40:05

使用 retain 属性指定应在新对象上调用 retain,并将先前的值发送为 release

因此,在第二个代码块中,对象的保留计数将变为 2,因为您不再释放它,并且 setter 正在保留它。这不太可能是您想要的。

Using the retain attribute specifies that retain should be invoked on the new object, and the previous value is sent a release.

So in your second code block, the retain count of the object would become 2, since you no longer release it, and the setter is retaining it. This is unlikely to be what you want.

离去的眼神 2024-10-04 06:40:05

如果将对象直接分配给属性,则仍然必须释放它:

self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];

If you assign the object directly to the property, you still must release it:

self.overlay = [[[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)] autorelease];
赏烟花じ飞满天 2024-10-04 06:40:05

由于您的属性是使用(保留)定义的,因此您使用合成设置器(通过 self.overlay 语法)设置的任何实例都会自动发送一条保留消息:

// You're alloc'ing and init'ing an object instance, which returns an 
// instance with a retainCount of 1.
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

// The overlay property is defined with (retain), so when you assign the new 
// instance to this property, it'll automatically invoke the synthesized setter, 
// which will send it a retain message. Your instance now has a retain count of 2.
self.overlay = tempOverlay;

// Send a release message, dropping the retain count to 1.
[tempOverlay release];

如果您这样做:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

您的覆盖层的保留计数将为 2,其中可能会在您的应用程序中的某个时刻导致泄漏。

As your property is defined with (retain) any instance you set using the synthesized setter (via the self.overlay syntax) will automatically be sent a retain message:

// You're alloc'ing and init'ing an object instance, which returns an 
// instance with a retainCount of 1.
UIView *tempOverlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

// The overlay property is defined with (retain), so when you assign the new 
// instance to this property, it'll automatically invoke the synthesized setter, 
// which will send it a retain message. Your instance now has a retain count of 2.
self.overlay = tempOverlay;

// Send a release message, dropping the retain count to 1.
[tempOverlay release];

If you were to do:

self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];

Your overlay would have a retain count of two, which will likely lead to a leak at some point in your application.

偏闹i 2024-10-04 06:40:05

感谢您的所有回答。我收到了一些相互冲突的声明,因此我在 UITableViewController 中测试了以下内容:

- (id)initWithStyle:(UITableViewStyle)style {
    if ((self = [super initWithStyle:style])) {
        NSLog(@"count: %d", [overlay retainCount]);
        self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
        NSLog(@"count: %d", [overlay retainCount]);
        [overlay release]; NSLog(@"released once");
        NSLog(@"count: %d", [overlay retainCount]);     
        [overlay release]; NSLog(@"released twice");
        NSLog(@"count: %d", [overlay retainCount]);
    }
    return self;
}

我得到了以下控制台输出:

  • 有时运行良好:

    <前><代码>计数:0
    数量:2
    释放一次
    数量:1
    发布两次
    数量:1

  • 其他时候崩溃:

    <前><代码>计数:0
    数量:2
    释放一次
    数量:1
    发布两次
    程序收到信号:“EXC_BAD_ACCESS”。

我知道使用 tempOverlay 的方法是正确的。它看起来很麻烦,但我更喜欢它而不是 autorelease 因为我不明白 autorelease 是如何工作的或何时调用它。有一点是肯定的。上面的代码是错误的,因为我不希望 overlay 的保留计数为 2。

奇怪的是我不能两次释放它。即使它没有崩溃,保留计数也不会减少。

不管怎样,我想我现在会继续使用 tempOverlay

Thank you for all the answers. I got some conflicting claims so I tested the following in a UITableViewController:

- (id)initWithStyle:(UITableViewStyle)style {
    if ((self = [super initWithStyle:style])) {
        NSLog(@"count: %d", [overlay retainCount]);
        self.overlay = [[UIView alloc] initWithFrame:CGRectMake(160.0f, 70.0f, 150.0f, 310.0f)];
        NSLog(@"count: %d", [overlay retainCount]);
        [overlay release]; NSLog(@"released once");
        NSLog(@"count: %d", [overlay retainCount]);     
        [overlay release]; NSLog(@"released twice");
        NSLog(@"count: %d", [overlay retainCount]);
    }
    return self;
}

I got the following console output:

  • Sometimes it ran fine:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    count: 1
    
  • Other times it crashed:

    count: 0
    count: 2
    released once
    count: 1
    released twice
    Program received signal:  “EXC_BAD_ACCESS”.
    

I know the method using tempOverlay is correct. It just seems so cumbersome, but I prefer it to autorelease because I don't understand how autorelease works or when it's called. One thing is for sure. The code above is wrong because I don't want overlay to have a retain count of 2.

The weird thing is that I can't release it twice. Even when it doesn't crash, the retain count is not decremented.

Anyway, guess I'll stick with using the tempOverlay for now.

一抹苦笑 2024-10-04 06:40:05

是的,您可以直接将新创建的对象分配给overlay对象。如果您愿意,您可以通过打印出对象的保留计数来向自己证明这一点

NSLog(@"count: %d", [overlay retainCount]);

Yes, you can directly assign the newly created object to overlay object. If you wish, you can prove it to yourself by printing out the retain count of the object

NSLog(@"count: %d", [overlay retainCount]);
~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文