为什么对象未在 dealloc 方法中解除分配



我在理解Objective-C和ARC时遇到了问题。

据我了解,强指针将自动为您解除分配,因此您不必考虑它(在 dealloc 方法中解除分配,或者在上次使用对象之后?

所以我写了一个小应用程序,有 2 个视图控制器和一个导航控制器,它进入一个视图然后返回。

调用了 dealloc 方法,但我在 viewDidLoad 方法中设置的属性没有解除分配,它仍然指向某个对象。

法典:第一个视图控制器有一个按钮,通过按下它,执行到另一个视图控制器的 segue。那里没有代码。

SecondViewController.m

@interface SecondViewController () 
@property (nonatomic, strong) NSString *myString;
@end
@implementation SecondViewController
- (void)viewDidLoad {
    [super viewDidLoad];
    NSLog(@"%@", _myString);
    _myString = @"it works";
}
- (void)dealloc {
    NSLog(@"%@", _myString);
    // and now it is deallocating the _myString property ???
}
@end

然后,我尝试做另一件事。

这个想法是创建一个弱指针,它指向与强指针相同的内存地址。不过,无论如何,弱指针都应该为零。

  1. 由于调用了 dealloc 方法,因此所有弱指针都应为零

  2. 由于强指针仅在 viewDidLoad 中使用,因此应该在 dealloc 方法之前解除分配。

问题是,它没有解除分配。为什么?

第二视图控制器的代码:

@interface SecondViewController ()
@property (nonatomic, strong) NSString *myString;
@property (nonatomic, weak) NSString *test;
@end
@implementation SecondViewController
- (void)viewDidLoad
{
    [super viewDidLoad];
    NSLog(@"%@", _myString);
    _myString = @"it works";
    _test = _myString;
}
- (void)dealloc
{
    NSLog(@"%@", _test);
}
@end

属性的释放发生在 dealloc 方法的末尾。如果覆盖 dealloc 方法,则尚未在该方法中释放属性。


您可以通过在第一个视图控制器

中创建弱属性来测试这一点,分配第二个视图控制器的强属性,然后在应用程序返回到第一个视图控制器时记录它的值。

说明weak引用的最简单方法是使用以下示例...

给定以下两个类:

@interface ObjectWithStrongRef : NSObject
@property (strong) NSString *ref;
@end
@interface ObjectWithWeakRef : NSObject
@property (weak) NSString *ref;
@end

我们将创建一个作用域大于ObjectWithStrongRef范围的ObjectWithWeakRef实例,为后者的ref属性赋值,然后让前者的ref指向同一对象,然后我们将检查两个作用域中的ref

int main(int argc, const char * argv[]) {
    ObjectWithWeakRef *weak = [[ObjectWithWeakRef alloc] init];
    @autoreleasepool {
        ObjectWithStrongRef *strong = [[ObjectWithStrongRef alloc] init];
        strong.ref = [NSString stringWithFormat:@"Hello %@", @"World"];
        weak.ref = strong.ref;
        NSLog(@"Weak.Ref = %@", weak.ref);
    }
    NSLog(@"Weak.Ref = %@", weak.ref);
}

请注意,我们不能简单地将ref分配给文字字符串。 Objective-C 倾向于将这些保留在内存中,以便它可以进行一些内存优化,但是当我们使用 stringWithFormat: 时,它会创建一个自动发布的字符串。

在第一个NSLog语句中,strong.ref保持对字符串对象的强引用,因此当我们登录weak.ref时,该对象尚未解除分配,因此它正确记录了"Hello World"。

在第一次和第二次NSLog调用之间,我们已经退出了@autoreleasepoolstrong对象的作用域在其中(如果我们在ObjectWithStrongRefdealloc中放置一条NSLog消息,我们会看到它在这里被调用(。 因为strong在我们退出@autoreleasepool时已经释放了,所以不再有任何对我们有引用的字符串对象的强引用——我们只有weak对内存的弱引用,所以字符串对象也会解除分配(就在strong解除分配之后(。

因此,在第二次NSLog调用中,我们将看到打印Weak.Ref = (null)

最新更新