ios - 为什么 weak for property 和 __weak for instance variable 表现不同

标签 ios objective-c memory-management properties

我知道 strong 和 weak 是属性声明中使用的修饰符,而 __strong 和 __weak 用于实例变量的声明...strong 表示只要我拥有它就将对象保留在内存中,weak 表示保留对象在内存中,只要其他人对它有很强的引用……对吧?但我不明白为什么 weak 属性和 __weak 例如变量的行为不同?这就是我想知道的......

 @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

这是结果日志

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.   ——??

弱实例变量在它们弱引用的对象之后打印(null),设置为 nil,这是预期的,但我想知道为什么弱属性 weakStringProperty 和 weakArrayProperty 仍然打印它们以前的值并且表现得像它们一样分别强指向strongStringProperty和strongArrayProperty??

谢谢 :)

最佳答案

weakStringProperty 不是 nil 因为 Foundation 仍在保留它。

当您调用[[NSString alloc]initWithFormat:@"Property"] 时,Foundation 决定将字符串作为NSTaggedPointerString 保留下来以备将来使用。您可以通过记录类来验证这一点:

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

我不确定系统使用哪些所有标准来决定创建这些字符串,但长度和可变性是因素。以下任一项都会得到您想要的结果。

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

// Mutable string
self.strongStringProperty = [[NSMutableString alloc]initWithFormat:@"Property"];

关于ios - 为什么 weak for property 和 __weak for instance variable 表现不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/41289853/

相关文章:

c++ - 小对象分配器

ios - 高分记忆不工作 Xcode

iphone - 从应用程序中添加到主屏幕?

iphone - 使用 wifi 和 3G 网络将文件从一个 ios 设备传输到另一个?

ios - 如何在iOS应用程序中添加Unity 3d的unity View?

c++ - ios NSURLConnectionDataDelegate didReceiveData 回调未调用

c - 从文件中读取并在动态结构上传输

ios - 在 iOS Interface Builder 中使用 StoryBoard 支持横向和纵向

ios - 未找到文件 tidy.h 和 buffio.h

memory-management - 为现有全局内存阵列分配更多内存