KudoCC
KudoCC

Reputation: 6952

arc and no-arc issues

This is my code

__weak KDObject *obj = [KDObject fetchObj] ;
NSLog(@"%@", obj) ; // I think it should be nil, but it is not
obj.i = 10 ;
NSLog(@"%d", obj.i) ;

In KDObject.m

@implementation KDObject    
+ (instancetype)fetchObj
{
    return [[self alloc] init] ;
}
@end

the result is the same whatever KDOjbect.m is compile with -fno-objc-arc flag or without -fno-objc-arc flag

Anybody has ideas why obj is not nil ?

Upvotes: 0

Views: 125

Answers (3)

Ryan
Ryan

Reputation: 4884

- (void)loadView
{
 [super loadView];

    TestObject *obj_ = [[TestObject alloc] init];
    pObj = obj_;
    if(pObj == nil)
    {
        NSLog(@"pObj_ is not nil");
    }

    __weak TestObject *obj2_ = [[TestObject alloc] init];
    if(obj2_ == nil)
    {
        NSLog(@"obj2_ is nil");
    }

    __weak TestObject *obj3_ = [TestObject createInstance];
    if(obj3_ == nil)
    {
        NSLog(@"obj3_ is nil");
    }
}

- (void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    if(pObj == nil)
    {
        NSLog(@"pObj is nil");
    }
}

KudoCC requested this code. I used LLVM5.1. If I use -fno-objc-arc to TestObject.h, the objc3_ became not nil.

Upvotes: -1

Amin Negm-Awad
Amin Negm-Awad

Reputation: 16660

Related to your Q and to your answer:

-fectchObject is a method not belonging to any method family with ownership transfer. Therefore ARC has to ensure that returning the reference is safe. That means that losing the strong reference in the local scope of -fetchObject does not give up the last reference.

One way to accomplish this is to use the autorelease pool. But ARC does not guarantee that the ARP is used. Moreover it tries not to use the ARP, because it is the solution with the highest memory pressure.

So the things happening depends of the compiler implementation, attributes set to the method and what the compiler sees in source code (esp. implementation of -fetchObject). So you should not rely on returning in ARP.

__weak is guaranteed to be nil, if the object is destroyed. But it is not guaranteed that the object is destroyed in the earliest possible moment. This is subject of optimization.

Upvotes: 2

Rukshan
Rukshan

Reputation: 8066

From the docs about __weak

__weak specifies a reference that does not keep the referenced object alive. A weak reference is set to nil when there are no strong references to the object.

Whether it's __weak or not KDObject *o = [[KDObject alloc] init] creates an object so o is not nil.

__weak is something realated to memory management. If none of strong objects are pointing to a weak object, it would be released from memory.

Upvotes: 0

Related Questions