Ios 何时释放对象,使用ARC将强引用指定给弱引用?
例如,如果我们有两个具有NSString属性的对象,一个是弱对象,另一个是强对象,如下所示Ios 何时释放对象,使用ARC将强引用指定给弱引用?,ios,objective-c,properties,automatic-ref-counting,Ios,Objective C,Properties,Automatic Ref Counting,例如,如果我们有两个具有NSString属性的对象,一个是弱对象,另一个是强对象,如下所示 @interface Class1 : NSObject @property (weak) NSString *weakString; @end @interface Class2 : NSObject @property (strong) NSString *strongString; @end 然后这样做: NSString *string = [[NSString alloc] initWit
@interface Class1 : NSObject
@property (weak) NSString *weakString;
@end
@interface Class2 : NSObject
@property (strong) NSString *strongString;
@end
然后这样做:
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;
甚至
c2 = nil;
那么c1.weakString包含什么呢
将字符串分配给strongString调用保留字符串,将字符串分配给nil将第一个版本发送给字符串,将strongString分配给weakString不会更改保留计数,然后将nil分配给strongString将第二个版本发送给字符串,甚至将nil分配给c2,所以释放c2应该将第二次释放发送到字符串,所以现在weakString(和so字符串)的重新计数应该为零,然后释放,所以如果我们试图访问它,weakString归零为零
但是'weakString'仍然包含“bla”,所以原始字符串对象,为什么
NSString
是一个类集群,在后台执行一些非直观的优化。如果您使用一些自定义的NSObject
子类而不是NSString
重复测试,它的行为将更像您期望的那样
想象一下您的示例的以下变化:
@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
然后考虑:
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);
您希望
weakString
和weakObject
都是nil
,但只有weakObject
是。这是在NSString
类中进行的一些内部实现优化的结果。取消分配不会立即发生
将您的实现放在@autoreleasepool
中,然后打印weakString,它将为零
(使用initWithFormat
进行字符串初始化,而不是冗余的initWithString
)
输出:str=(空)
现在,如果您将weakString属性更改为“强”而不是“弱”
@property (strong) NSString *weakString;
输出:str=bla
只要您至少有一个强引用,就不应该将对象解除分配/设置为
nil
。我知道,但在将nil分配给strongString和string之后,强引用不应该再存在,或者我错了?哦,如果您担心的话:解除分配不会立即发生。它可能会稍微延迟。解除分配发生在下一个运行循环周期,但问题是根本没有发生,但如果跳过强分配,则会发生解除分配immediatelly@Rob我这样做了,行为没有改变谢谢,我做了测试,它按预期工作,因此,似乎分配给属性strong的对象(即使该属性已设置为nil)在自动释放池未耗尽之前不会释放。但是当当前的自动释放池实际耗尽时?@Manu我根本不清楚weak
NSString
属性是nil
-ed。我修改了上面的示例,使视图控制器的c1
和c2
类属性,很久以后,当我检查c1
的weak
属性时,weakString
仍然报告一个值,即使应用程序早已删除了对它的任何强引用。总之,我不会依赖对NSString
的weak
引用来报告nil
,即使你的应用程序不再有任何strong
引用。当对象被释放时,weak变量被设置为nil。在NSString情况下,字符串对象可能不会被释放,因为它是一个不朽常量字符串。在其他情况下,对象可能尚未解除分配,因为它已自动释放,并且自动释放池尚未耗尽。
@property (strong) NSString *weakString;