Reputation: 1127
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 :)
Upvotes: 6
Views: 790
Reputation: 52538
Your properties are atomic, because you didn't declare them nonatomic. Atomic properties return an object that is retained and autoreleased, so the object will remain in the autorelease pool and very remain retained 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 the weak properties will likely be nil.
However, iOS quite often creates objects that will never be released. For example, there is one empty NSArray object which will never, ever be released. Same for many NSNumber objects, short strings, @YES and @NO and others. There is no guarantee that an object will be deallocated when you think it would be, and therefore no guarantee that a weak object becomes nil.
Upvotes: 1
Reputation: 27550
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"];
Upvotes: 1