Search code examples
iphoneautomatic-ref-countingretainweak

iOS ARC - weak and strong properties


I'm trying to understand the way ARC works, and as far as I know, I should be doing something wrong here. This is the code I'm using:

Interface:

@interface ViewController : UIViewController{

}

@property (strong, nonatomic) NSString * myString ; 
@property (weak, nonatomic) NSString * myPointer ;

Implementation:

 - (void)viewDidLoad{

     [super viewDidLoad];
     self.myString = @"Hello world!" ; // myString is strong
     self.myPointer = self.myString ; // myPointer var is weak

     [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
     [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

 - (void) makeNilMyValue{
     self.myString = nil ; 
}

 - (void) printValues{
     NSLog(@"myString: %@", self.myString) ;
     NSLog(@"myPointer: %@", self.myPointer) ; 
 }

After executing this, I get:

2012-02-26 11:40:41.652 test1[933:207] myString: (null)

2012-02-26 11:40:41.653 test1[933:207] myPointer: Hello world!

If I'm not wrong, due to myPointer is weak, it shouldn't retain the content of the object. So, it should show nil instead of "Hello World!".

What am I doing wrong?

Following Caleb's answer, I have created another weak pointer, see code below:

- (void)viewDidLoad{
    [super viewDidLoad];
    self.myString = @"Hello world!" ; // myString is strong
    self.myPointer = self.myString ; // myPointer var is weak
    self.myPointer2 = self.myString ; // myPointer2 var is weak

    [self performSelector:@selector(makeNilMyValue) withObject:nil afterDelay:1];    
    [self performSelector:@selector(printValues) withObject:nil afterDelay:2];    
}

- (void) makeNilMyValue{
    self.myPointer2 = @"value changed!" ;
    self.myString = nil ;

}

- (void) printValues{
    NSLog(@"myString: %@", self.myString) ;
    NSLog(@"myPointer: %@", self.myPointer) ;
}

The point is that I still got the same answer I used to have:

2012-02-26 12:08:13.426 test1[1333:207] myString: (null)
2012-02-26 12:08:13.427 test1[1333:207] myPointer: Hello world!

Solution

  • As Caleb pointed out, using a constant NSString for this example is not a good idea.

    The simplest way to create a string object in source code is to use the Objective-C @"..." construct:

    NSString *temp = @"/tmp/scratch"; Note that, when creating a string constant in this fashion, you should avoid using anything but 7-bit ASCII characters. Such an object is created at compile time and exists throughout your program’s execution. The compiler makes such object constants unique on a per-module basis, and they’re never deallocated, though you can retain and release them as you do any other object. You can also send messages directly to a string constant as you do any other string:

    BOOL same = [@"comparison" isEqualToString:myString];

    The documentation explains that constant strings will never disappear.

    Try using something else for your experiment. I tried NSObject and it produced expected results.

    Interface:

    @interface ViewController : UIViewController
    
    @property (strong, nonatomic) NSObject * myString; 
    @property (weak, nonatomic) NSObject * myPointer;
    
    @end
    

    Implementation:

    @implementation ViewController
    
    @synthesize myString = _myString;
    @synthesize myPointer = _myPointer;
    
    - (void)viewDidLoad{
    
        [super viewDidLoad];
    
        self.myString = [[NSObject alloc] init];
        self.myPointer = self.myString;
        self.myString = nil; 
        NSLog(@"myString: %@", self.myString);
        NSLog(@"myPointer: %@", self.myPointer);
    }
    
    - (BOOL)shouldAutorotateToInterfaceOrientation:(UIInterfaceOrientation)interfaceOrientation
    {
        return (interfaceOrientation != UIInterfaceOrientationPortraitUpsideDown);
    }
    
    @end
    

    Weak pointers are set to nil when there are no strong pointers to the memory as explained in the documentation - Apple Developer or llvm.

    __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.