ARC 弱局部变量的生命周期
如果我有一段如下所示的代码:
- (void)testSomething
{
__weak NSString *str = [[NSString alloc] initWithFormat:@"%@", [NSDate date]];
NSLog(@"%@", str);
}
输出将为 (null),因为没有对 str 的强引用,并且在分配它后它将立即释放。这是有道理的,并且在过渡到 ARC 指南中有详细说明。
如果我的代码如下所示:
- (void)testSomething
{
__weak NSString *str = [NSString stringWithFormat:@"%@", [NSDate date]];
NSLog(@"%@", str);
}
那么它会正确打印出当前日期。显然,您希望它能够在非 ARC 世界中工作,因为 str
会自动释放,因此在该方法退出之前都有效。然而,在启用 ARC 的代码中,人们通常认为这两种形式 (stringWithFormat
和 alloc/initWithFormat
) 是等效的。
所以我的问题是像第二个例子这样的代码是否能保证在 ARC 下工作。也就是说,如果我对通过我们通常认为的自动释放便利构造函数获得的对象有一个弱引用,那么在我通常会使用的同一范围内使用该引用是否保证是安全的有没有 ARC(即直到方法退出)?
If I have a piece of code that looks like this:
- (void)testSomething
{
__weak NSString *str = [[NSString alloc] initWithFormat:@"%@", [NSDate date]];
NSLog(@"%@", str);
}
the output will be (null) because there are no strong references to str and it will be immediately released after I allocate it. This makes sense and is spelled out in the Transitioning to ARC guide.
If my code looks like this:
- (void)testSomething
{
__weak NSString *str = [NSString stringWithFormat:@"%@", [NSDate date]];
NSLog(@"%@", str);
}
then it correctly prints out the current date. Obviously you would expect it to work in a non-ARC world, since str
would be autoreleased and therefore valid until this method exits. However, in ARC-enabled code people generally consider the two forms (stringWithFormat
& alloc/initWithFormat
) to be equivalent.
So my question is whether code like the second example is guaranteed to work under ARC. That is, if I have a weak reference to an object that I get via what we would normally consider an autoreleasing convenience constructor, is it guaranteed to be safe to use that reference in the same scope I normally would have without ARC (i.e. until the method exits)?
如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

绑定邮箱获取回复消息
由于您还没有绑定你的真实邮箱,如果其他用户或者作者回复了您的评论,将不能在第一时间通知您!
发布评论
评论(2)
自动释放和分配的约定在 ARC 世界中仍然适用。唯一的区别是 ARC 将插入额外的保留/释放调用,使泄漏对象或访问已释放的对象变得更加困难。
在此代码中:
保留(或等效)对象的唯一位置是分配。 ARC会自动插入一个释放命令,使其立即被释放。
同时,在这段代码中:
按照惯例,像这样的便利构造函数的返回值必须是一个自动释放的对象*。这意味着当前的自动释放池已保留该对象,并且在池耗尽之前不会释放它。因此,您几乎可以保证该对象至少在您的方法的持续时间内存在 - 尽管您可能不应该依赖这种行为。
(*或以其他方式保留)
The conventions of autoreleasing and allocing still apply in the world of ARC. The only difference is that ARC will insert extra retain/release calls to make it much harder to leak objects or access a dealloced object.
In this code:
The only place the object is retained (or equivalent) is the alloc. ARC will automatically insert a release command, causing it to be immediately dealloced.
Meanwhile, in this code:
By convention, the return value of a convenience constructor like this must be an autoreleased object*. That means the current autoreleasepool has retained the object and will not release it until the pool is drained. You are therefore all but guaranteed that this object will exist for at least the duration of your method - although you probably shouldn't rely on this behaviour.
(* or retained in some other way)
局部弱变量的生命周期根本无法保证。如果该变量指向的对象被释放,则该弱变量随后将指向
nil
。如果您对通过不返回保留对象的方法获得的对象有弱引用,则假设该对象在方法退出之前一直存在是不安全的。如果要确保对象存活,请使用强引用。
下面是一个示例,显示非保留方法的返回值不能保证最终出现在自动释放池中:
将此方法添加到
AppDelegate.m
:替换
-application:didFinishLaunchingWithOptions:
:重要:现在将调试的优化级别设置为
-Os
.在此示例中,
+[AppDelegate anObject]
的作用类似于便捷构造函数,但如果您在使用-Os 的设备上执行它,您将看到记录
(null)
优化。其原因是巧妙的 ARC 优化,可以防止将对象添加到自动释放池的开销。您可能已经注意到,我不再使用
+[NSString stringWithFormat:]
这样的库方法。这些似乎总是将对象放入自动释放池中,这可能是出于兼容性原因。The lifetime of a local weak variable is not guaranteed at all. If the object that the variable points to is deallocated, the weak variable will point to
nil
afterwards.If you have a weak reference to an object that you got via a method that does not return a retained object, it is not safe to assume that this object lives until the method exits. If you want to make sure that the object survives, use a strong reference.
Here is an example that shows that a non-retaining method's return value is not guaranteed to end up in the autorelease pool:
Add this method to the
AppDelegate.m
:Replace
-application:didFinishLaunchingWithOptions:
:Important: Now set the Optimization level for Debug to
-Os
.In this example,
+[AppDelegate anObject]
acts like a convenience constructor, but you will see(null)
logged if you execute it on a device with-Os
optimization. The reason for that is a nifty ARC optimization that prevents the overhead of adding the object to the autorelease pool.You may have noticed that I switched to not using a library method like
+[NSString stringWithFormat:]
. These seem to always put objects in the autorelease pool, that may be for compatibility reasons.