When the object will be released assigning a strong reference to a weak reference, using ARC?
例如,如果我们有两个具有nsstring属性的对象,一个是弱的,另一个是强的,就像这样
1 2 3 4 5 6 7 8 | @interface Class1 : NSObject @property (weak) NSString *weakString; @end @interface Class2 : NSObject @property (strong) NSString *strongString; @end |
然后这样做:
1 2 3 4 5 6 7 8 9 10 11 | NSString *string = [[NSString alloc] initWithString:@"bla"]; Class2 *c2 = [[Class2 alloc] init]; c2.strongString = string; string = nil; Class1 *c1 = [[Class1 alloc] init]; c1.weakString = c2.strongString; c2.strongString = nil; |
甚至
1 | c2 = nil; |
那么,c1.weakstring包含什么呢?
将字符串赋给strongstring调用保留字符串,将字符串赋给nil发送第一个释放给字符串,将strongstring赋给weakstring不更改保留计数,然后将nil赋给strongstring发送第二个释放给字符串,甚至将nil赋给c2,因此释放c2应将第二个释放发送给字符串,并且所以现在weakString(和so-string)的retaincount应该是零,然后释放,如果我们试图访问它,weakString将为零
但是"weakString"仍然包含"bla",所以原始的字符串对象,为什么?
想象一下您的例子中的以下变化:
1 2 3 4 5 6 7 8 9 10 11 12 | @interface MyTestObject : NSObject @end @interface Class1 : NSObject @property (weak) NSString *weakString; @property (weak) MyTestObject *weakObject; @end @interface Class2 : NSObject @property (strong) NSString *strongString; @property (strong) MyTestObject *strongObject; @end |
然后考虑:
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 19 20 21 22 | Class2 *c2 = [[Class2 alloc] init]; Class1 *c1 = [[Class1 alloc] init]; @autoreleasepool { NSString *string = [[NSString alloc] initWithString:@"bla"]; MyTestObject *object = [[MyTestObject alloc] init]; c2.strongString = string; c2.strongObject = object; string = nil; object = nil; c1.weakString = c2.strongString; c1.weakObject = c2.strongObject; c2.strongString = nil; c2.strongObject = nil; } NSLog(@"c1.weakString = %@", c1.weakString); NSLog(@"c1.weakObject = %@", c1.weakObject); |
你会认为
您计算的保留计数是正确的。
ARC只是在编译时为您添加保留/释放代码,因此基本规则与手动管理内存相同。当retain count为零时,将立即解除锁定。
上面的示例是一个特殊的情况:nsstring处于为性能而管理的特殊内存下。字符串内容是不可变的。相同的字符串内容将指向相同的内存地址,以避免多次重复。nsstring保留计数太大,无法释放。
释放不会立即发生。
将您的实现放在
(使用
1 2 3 4 5 6 7 8 9 10 11 12 13 14 15 16 17 18 | Class2 *c2 = nil; Class1 *c1 = nil; @autoreleasepool { NSString *string = [[NSString alloc] initWithFormat:@"bla"]; c2 = [[Class2 alloc] init]; c2.strongString = string; string = nil; c1 = [[Class1 alloc] init]; c1.weakString = c2.strongString; c2.strongString = nil; } NSLog(@"str = %@", c1.weakString); |
输出:str=(空)
现在,如果将WeakString属性改为"强"而不是"弱"
1 | @property (strong) NSString *weakString; |
输出:str=bla