And why can it vary between Debug/Release/Simulator/Device combinations? (Sample code below.)
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.
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)
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.
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