为什么在实例方法中弱成员在方法完成之前可以为空? [英] Why can a weak member be nulled in an instance method before the method is finished?
问题描述
为什么它在调试/发行版/仿真器/设备组合之间会有所不同? (下面的示例代码.)
And why can it vary between Debug/Release/Simulator/Device combinations? (Sample code below.)
我继承了一些在模拟器中和调试"中的设备上有效"的代码,但在Release(以前的LLVM中使用)的设备上不起作用.它与ARC和较弱的属性(本来应该很强)有关,但是我不完全了解正在发生的事情,希望有人可以向我解释它,以及为什么它在Debug/Release/Device/Simulator之间有所不同.
I inherited some code that "works" in the simulator and on devices in Debug, but not on a device in Release (used to with last LLVM). It's related to ARC and a weak property (which should have been strong), but I don't understand fully what's happening and am hoping someone can explain it to me and why it varies between Debug/Release/Device/Simulator.
我创建了一个简单的示例项目来演示此过程,其中包含AppDelegate.m中的所有代码,如下所示.在模拟器中运行时,记录的输出为:
I created a simple sample project that demonstrates this, with all code in AppDelegate.m as included below. When run in the simulator, the logged output is:
-[BaseThingMaker baseMakeThing]: returning a Thing
-[ThingMaker makeThing]: returning a Thing
-[AppDelegate application:didFinishLaunchingWithOptions:]: got a Thing
在设备上运行时,记录的输出为:
When run on the device, the logged output is:
-[BaseThingMaker baseMakeThing]: returning a Thing
-[ThingMaker makeThing]: returning a (null)
-[AppDelegate application:didFinishLaunchingWithOptions:]: got a (null)
在设备上(在Debug或Release中),即使方法完成之前的日志消息,在ThingMaker
中的弱self.thing
也为空.在模拟器上,返回self.thing
对象.
On a device (in Debug or Release), the weak self.thing
in ThingMaker
is null even for the log message before the method is complete. On the simulator, the self.thing
object is returned.
单窗口应用程序(AppDelegate.m)中的示例代码:
Sample code from Single Window App (AppDelegate.m):
#import "AppDelegate.h"
@interface Thing : NSObject
@end
@implementation Thing
@end
@interface BaseThingMaker : NSObject
-(Thing *)baseMakeThing;
@end
@implementation BaseThingMaker
-(Thing *)baseMakeThing
{
Thing *thing = [Thing new];
NSLog(@"%s: returning a %@", __PRETTY_FUNCTION__, NSStringFromClass([thing class]));
return thing;
}
@end
@interface ThingMaker : NSObject
- (id)makeThing;
@end
@interface ThingMaker ()
@property (weak, nonatomic) id thing;
@end
@implementation ThingMaker
- (id)makeThing
{
BaseThingMaker *baseThingMaker = [BaseThingMaker new];
self.thing = [baseThingMaker baseMakeThing];
NSLog(@"%s: returning a %@", __PRETTY_FUNCTION__, NSStringFromClass([self.thing class]));
return self.thing;
}
@end
@implementation AppDelegate
- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
ThingMaker *thingMaker = [ThingMaker new];
id thingIWant = [thingMaker makeThing];
NSLog(@"%s: got a %@", __PRETTY_FUNCTION__, NSStringFromClass([thingIWant class]));
return YES;
}
@end
推荐答案
方法baseMakeThing
不返回其调用拥有的对象,在这种情况下,它返回一个自动释放的对象.如果它是一个自动释放的对象,它将拥有一个所有者-自动释放池-直到运行循环循环时将其清空的池为止.因此,对弱属性的赋值在此之前一直有效,并且代码出现可以正常工作...
The method baseMakeThing
does not return an object its call owns, in this case it returns an autoreleased object. If it is an autoreleased object it will have an owner - the autorelease pool - until the pool it emptied when the run loop cycles around. So the assignment to the weak property will be valid until that happens, and the code will appear to work...
除非,编译器会进行优化,而不是保留自动发布的对象,编译器有时可以将对象从自动发布池中拉出,并以此方式取得所有权.如果编译器执行此操作,则在分配给弱属性后,编译器可以立即放弃所有权,因为稍后在makeThing
中不再使用该引用,这反过来将使弱属性为空...
Unless the compiler optimises, instead of retaining an autoreleased object the compiler can sometimes pull the object out of the autorelease pool and take ownership that way. If the compiler does this then immediately after the assignment to the weak property the compiler can relinquish ownership, as the reference is not used later in makeThing
, and this will in turn null the weak property...
您看到的差异取决于编译器根据构建类型进行的优化程度.
The differences you are seeing are down to how much optimisation the compiler is doing depending on the type of build.
这篇关于为什么在实例方法中弱成员在方法完成之前可以为空?的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!