为什么在dealloc方法中没有释放对象?

时间:2015-03-25 20:21:32

标签: ios objective-c memory-management memory-leaks dealloc

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

据我所知,强指针会自动为你解除分配,所以你不必考虑它(在dealloc方法中解除分配,或者在最后一次使用对象之后?)。

所以我写了一个小应用程序,带有2个viewControllers和一个NavigationController,它进入一个视图然后返回。

调用了dealloc方法,但是我在viewDidLoad方法中设置的属性没有被释放,它仍然指向某个对象。

代码: 第一个viewController有一个按钮,通过按下它,可以执行另一个viewController的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方法之前取消分配。

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

    secondViewController的代码:

    @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
    

2 个答案:

答案 0 :(得分:3)

在dealloc方法结束时发生属性的释放。如果覆盖dealloc方法,则该方法中的属性尚未解除分配。


您可以通过在第一个视图控制器中创建一个weak属性来测试它,分配第二个视图控制器的strong属性,然后在应用程序返回到第一个视图控制器时记录它的值。

答案 1 :(得分:3)

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

鉴于以下两个类:

@interface ObjectWithStrongRef : NSObject

@property (strong) NSString *ref;

@end

@interface ObjectWithWeakRef : NSObject

@property (weak) NSString *ref;

@end

我们将创建一个ObjectWithWeakRef的实例,其范围大于ObjectWithStrongRef的范围,为后者的ref属性赋值,然后使用前者' s 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时,该对象尚未解除分配,因此它正确记录&# 34; Hello World"。

在第一次和第二次NSLog来电之间,我们已退出@autoreleasepool,其中strong对象的作用域(如果我们发出NSLog条消息在ObjectWithStrongRef' dealloc中,我们在这里看到了它。因为我们退出strong@autoreleasepool已取消分配,所以我们不再引用对我们引用的字符串对象的强引用 - 我们只有weak的弱引用到内存,所以字符串对象解除分配(在strong解除分配之后)。

因此,在第二次NSLog来电中,我们会看到Weak.Ref = (null)已打印出来。