0

Though it's kind of stupid in 2020 that I'm still asking question about ObjC, please be patient and considerate...

I'm reading the source code of BloksKit and ran into a weird situation.

#import <objc/runtime.h>

@interface _WeakAssociatedObjectWrapper : NSObject
@property (nonatomic, weak) id object;
@end

@implementation _WeakAssociatedObjectWrapper
@end

@interface NSObject (AddWeak)
@end

@implementation NSObject (AddWeak)
- (void)setWeakProp:(id)weakProp {
    _WeakAssociatedObjectWrapper *wrapper  = objc_getAssociatedObject(self, @selector(weakProp));
    if (!wrapper) {
        wrapper = [[_WeakAssociatedObjectWrapper alloc] init];
        objc_setAssociatedObject(self, @selector(weakProp), wrapper, OBJC_ASSOCIATION_RETAIN_NONATOMIC);
    }
    wrapper.object = weakProp;
}
- (id)weakProp {
    id value = objc_getAssociatedObject(self, _cmd);
    if ([value isKindOfClass:_WeakAssociatedObjectWrapper.class]) {
        return [(_WeakAssociatedObjectWrapper *)value object];
    }
    return value;
}
@end

int main(int argc, const char * argv[]) {
    @autoreleasepool {
        NSObject *obj = [[NSObject alloc] init];
        {
            NSObject *prop = [[NSObject alloc] init];
            [obj setWeakProp:prop];

            [obj weakProp]; // *Weird!!
        }
        NSLog(@"Now obj.weakProp = %@", [obj weakProp]);
    }
    return 0;
}

This code is adding a weak associated object for category.(BlocksKit does so)

Note the *Weird!! line. If this line is commented out, then it prints (null), which is reasonable since prop is deallocated outside the {} scope. On the other side, if not commented out, it prints <NSObject: 0xxxxx>, which indicates that prop is somehow retained by someone(Or any other reason?). What is happening here??! (BlocksKit behaves the same!)

Environment: XCode 10.3

刘maxwell
  • 187
  • 10

1 Answers1

0

This is a feature. For the case (and any similar)

[obj weakProp];

by properties/accessors naming convention ARC returns autoreleased instance, so in your case @autoreleasepool holds it and testing as below can show this.

int main(int argc, const char * argv[]) {
    NSObject *obj = [[NSObject alloc] init];
    @autoreleasepool {
        {
            NSObject *prop = [[NSObject alloc] init];
            [obj setWeakProp:prop];

            [obj weakProp]; // *Weird!!
        }
        NSLog(@"Now obj.weakProp = %@", [obj weakProp]);
    }
    NSLog(@"After autoreleased >> obj.weakProp = %@", [obj weakProp]);
    return 0;
}
Asperi
  • 228,894
  • 20
  • 464
  • 690