Why can a weak member be encoded in an instance method before the method completes?

And why can this vary between debug / release / sim / sim combinations? (Sample code below.)

I inherited some code that "works" in the simulator and on devices in Debug, but not on the device in Release (used with the latest LLVM). This is due to ARC and a weak property (which should have been strong), but I do not quite understand what is happening, and I hope someone can explain this to me and why it changes between Debug / Release / Device / Simulator.

I created a simple sample project demonstrating this, with all the code in AppDelegate.m, as follows. When run in the simulator, the logged output:

-[BaseThingMaker baseMakeThing]: returning a Thing -[ThingMaker makeThing]: returning a Thing -[AppDelegate application:didFinishLaunchingWithOptions:]: got a Thing 

When starting on the device, the registered output:

 -[BaseThingMaker baseMakeThing]: returning a Thing -[ThingMaker makeThing]: returning a (null) -[AppDelegate application:didFinishLaunchingWithOptions:]: got a (null) 

On the device (in Debug or Release), weak self.thing in ThingMaker is zero even for a log message before the method completes. On the simulator, the self.thing object is self.thing .

Sample code from a single-window application (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 
0
source share
1 answer

The baseMakeThing method baseMakeThing not return the object to which its call belongs, in this case it returns an object with auto-implementation. If it is an auto-implemented object, it will have an owner - the pool of autoresists - until the pool drops, when the cycle cycle moves cyclically. Thus, the assignment of weak property will be valid until this happens, and the code will work ...

If the compiler is not optimized, instead of saving the object with auto-implementation, the compiler can sometimes pull the object out of the autorun pool and thus own it. If the compiler does this, then immediately after assigning weak ownership, the compiler can waive ownership, since the link will not be used later in makeThing , and this, in turn, will result in zero weak property ...

The differences you see boil down to how optimized the compiler is depending on the type of assembly.

+2
source

All Articles