简体   繁体   English

为什么属性弱和实例变量__weak表现不同

[英]why weak for property and __weak for instance variable behave differentenly

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 im owning it and weak says that keep the object in memory as long as someone else having a strong reference to it... right? 我知道强和弱是在属性声明中使用的修饰符,而__strong和__weak在实例变量的声明中使用...强表示将对象保留在内存中,只要我拥有它;而弱表示将对象保留在内存中,即只要其他人对此有强烈的参考...对吗? but i not getting why weak for property and __weak for instance variable behaves differently ?? 但我不明白为什么属性弱和实例变量__weak表现不同? 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 im 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?? 两个弱实例变量在它们被弱引用的对象之后都打印(空),并且都设置为nil,这与预期的一样,但是我想知道为什么弱属性weakStringProperty和weakArrayProperty仍然打印其先前的值并表现出强烈的指向性strongStringProperty和strongArrayProperty分别是?

Thanks :) 谢谢 :)

weakStringProperty isn't nil because it Foundation is still retaining it. weakStringProperty并不nil因为它仍在保留它。

When you called [[NSString alloc]initWithFormat:@"Property"] , Foundation decided to intern the string as a NSTaggedPointerString which it then retained for future use. 当您调用[[NSString alloc]initWithFormat:@"Property"] ,Foundation决定将该字符串作为NSTaggedPointerString进行内联,然后保留以备将来使用。 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"];

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. 原子属性返回保留并自动释放的对象,因此该对象将保留在自动释放池中,并且非常保留,直到您退出viewDidLoad方法。

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. 但是,iOS通常会创建永远不会释放的对象。 For example, there is one empty NSArray object which will never, ever be released. 例如,有一个空的NSArray对象永远不会被释放。 Same for many NSNumber objects, short strings, @YES and @NO and others. 对于许多NSNumber对象,短字符串,@ YES和@NO以及其他对象,情况相同。 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. 无法保证在您认为某个对象会被释放时就将其解除分配,因此不能保证弱对象变为零。

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM