Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

why weak for property and __weak for instance variable behave differentenly

I know that strong and weak are modifiers used in property declarations while __strong and __weak are used in declarations of instance variables... strong says that keep the object in memory as long as i m owning it and weak says that keep the object in memory as long as someone else having a strong reference to it... right? but i not getting why weak for property and __weak for instance variable behaves differently ?? Here is what i wondered...

 @interface DemoViewController (){

    __weak NSArray *weakArray;
    __strong NSArray *strongArray;
    __weak NSString *weakString;
    __strong NSString *strongString;  
 }

@property (weak) NSString *weakStringProperty;
@property (strong) NSString *strongStringProperty;

@property (weak) NSArray *weakArrayProperty;
@property (strong) NSArray *strongArrayProperty;

@end

@implementation DemoViewController

- (void)viewDidLoad {
    [super viewDidLoad];

    strongArray = [[NSArray alloc] initWithObjects:@"one",@"two", nil];
    weakArray = strongArray;

    NSLog(@"Round:1 strongArray is %@.", strongArray);
    NSLog(@"Round:1 weakArray is %@.", weakArray);

    strongArray = nil;

    NSLog(@"Round:2 strongArray is %@.", strongArray);
    NSLog(@"Round:2 weakArray is %@.", weakArray);

    self.strongArrayProperty = [[NSArray alloc] initWithObjects:@"one",@"two", nil];
    self.weakArrayProperty = self.strongArrayProperty;

    NSLog(@"Round:1 strongArrayProperty is %@.", self.strongArrayProperty);
    NSLog(@"Round:1 weakArrayProperty is %@.", self.weakArrayProperty);

    self.strongArrayProperty = nil;

    NSLog(@"Round:2 strongArrayProperty is %@.", self.strongArrayProperty);
    NSLog(@"Round:2 weakArrayProperty is %@.", self.weakArrayProperty);


    strongString = [[NSString alloc]initWithFormat:@"instanceVariable"];
    weakString = strongString;

    NSLog(@"Round:1 strongString is %@.", strongString);
    NSLog(@"Round:1 weakString is %@.", weakString);

    strongString = nil;

    NSLog(@"Round:2 strongString is %@.", strongString);
    NSLog(@"Round:2 weakString is %@.", weakString);

    self.strongStringProperty = [[NSString alloc]initWithFormat:@"Property"];
    self.weakStringProperty = self.strongStringProperty;

    NSLog(@"Round:1 strongStringProperty is %@.", self.strongStringProperty);
    NSLog(@"Round:1 weakStringProperty is %@.", self.weakStringProperty);

    self.strongStringProperty = nil;

    NSLog(@"Round:2 strongStringProperty is %@.", self.strongStringProperty);
    NSLog(@"Round:2 weakStringProperty is %@.", self.weakStringProperty);

}
@end

And here are the resulted logs

Round:1 strongArray is (
    one,
    two
).
 Round:1 weakArray is (
    one,
    two
).
 Round:2 strongArray is (null).
 Round:2 weakArray is (null).


 Round:1 strongArrayProperty is (
    one,
    two
).
Round:1 weakArrayProperty is (
    one,
    two
).
Round:2 strongArrayProperty is (null).
Round:2 weakArrayProperty is (
    one,
    two
).           —???

Round:1 strongString is instanceVariable.
Round:1 weakString is instanceVariable.
Round:2 strongString is (null).
Round:2 weakString is (null).


Round:1 strongStringProperty is Property.
Round:1 weakStringProperty is Property.
Round:2 strongStringProperty is (null).
Round:2 weakStringProperty is Property.   ——??

Both weak instance variables print (null) after the objects they were weakly referring to, are set to nil and this's as expected but i m wondering why both the weak properties weakStringProperty and weakArrayProperty are still print their previous values and behaving like they were strongly pointing to strongStringProperty and strongArrayProperty respectively??

Thanks :)

like image 273
Dipika Avatar asked Dec 22 '16 18:12

Dipika


1 Answers

weakStringProperty isn't nil because it Foundation is still retaining it.

When you called [[NSString alloc]initWithFormat:@"Property"], Foundation decided to intern the string as a NSTaggedPointerString which it then retained for future use. You can validate this by logging the class:

NSLog(@"kindof: %@", [self.weakStringProperty class]);

I'm not sure what all criteria the system uses to decide to create these strings, but length and mutability are factors. Either of the following would get your desired result.

// Longer string
self.strongStringProperty = [[NSString alloc]initWithFormat:@"Property la la la"];

// Mutable string
self.strongStringProperty = [[NSMutableString alloc]initWithFormat:@"Property"];
like image 197
Brian Nickel Avatar answered Oct 22 '22 04:10

Brian Nickel