Why is weak for a property and __weak, like a variable, behave differently

I know that strong and weak modifiers are used in property declarations, while __strong and __weak are used in instance variable declarations ... strong says to keep an object in memory while they belong, and a weak one says to keep an object in memory while someone else has a strong link to it ... right? but I don’t understand why the weak for the property and __weak, for example, does the variable behave 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 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 print (null) instance variables after the objects they weakly referenced are set to nil, and this is as expected, but they wonder why the weak properties weakStringProperty and weakArrayProperty still print their previous values ​​and behave like this as they were strongly pointing to strongStringProperty and strongArrayProperty respectively.

Thanks:)

+6
source share
2 answers

weakStringProperty not nil because Foundation still saves it.

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

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

I'm not sure what all the criteria the system uses to decide to create these lines, but length and variability are factors. Any of the following options will get the desired result.

 // Longer string self.strongStringProperty = [[NSString alloc]initWithFormat:@"Property la la la"]; // Mutable string self.strongStringProperty = [[NSMutableString alloc]initWithFormat:@"Property"]; 
+1
source

Your properties are atomic because you did not declare them non-atomic. Atomic properties return an object that is saved and auto-implemented, so the object will remain in the autorun pool and remain unchanged until you exit the viewDidLoad method.

Change for example to

 @property (weak, nonatomic, readwrite) NSString *weakStringProperty; 

and you are more likely to get the expected result. Or check the properties in another method later, and weak properties are likely to be zero.

However, iOS often creates objects that will never be released. For example, there is one empty NSArray that will never be released. The same goes for many NSNumber objects, short lines, @YES and @NO and others. There is no guarantee that the object will be freed if you think it will, and therefore does not guarantee that the weak object will become null.

+1
source

Source: https://habr.com/ru/post/1013437/


All Articles