为什么在实例方法中弱成员在方法完成之前可以为空? [英] Why can a weak member be nulled in an instance method before the method is finished?

查看:92
本文介绍了为什么在实例方法中弱成员在方法完成之前可以为空?的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

为什么它在调试/发行版/仿真器/设备组合之间会有所不同? (下面的示例代码.)

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屋!

查看全文
相关文章
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆