gpt4 book ai didi

ios - 是否可以在保留计数不为零的对象上调用 dealloc?

转载 作者:塔克拉玛干 更新时间:2023-11-02 09:22:58 25 4
gpt4 key购买 nike

我会尽量简短明了:我有一个对象,它的 dealloc 方法正在被调用。我还有一个 NSTimer 每 3 秒被调用一次以记录以控制所述对象的当前保留计数。

需要说明的是:我知道 NSTimer 会保留该对象。即使考虑到这一点,情况仍然不成立。

无论如何 - 在这个计时器触发时,对象的保留计数被记录为 3。这让我感到困惑有两个原因:

  1. 如果对象的保留计数从未达到 0,为什么要调用 dealloc?
  2. 既然 dealloc 被调用,至少,保留计数不应该是 1,因为 NSTimer 实例正在保留它?

非常感谢任何帮助。谢谢。

编辑:代码:

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(logRetainCount) userInfo:nil repeats:YES];

^ 在 vi​​ewDidLoad 中设置

- (void)logRetainCount
{
NSLog(@"own retain count: %ld", CFGetRetainCount((__bridge CFTypeRef)self));
}

^ 日志保留计数的方法

- (void)dealloc {
NSLog(@"view controller deallocated");
}

^ VC 中实现的应该被释放的 dealloc 方法

控制台输出:

own retain count: 5

view controller deallocated

own retain count: 3

最佳答案

你问:

Is it possible for dealloc to be called on an object whose retain count is NOT zero?

由于您使用的是 ARC,我们不再在该上下文中使用“保留计数”。但是在回答你的问题时,不,在有强引用的情况下不能释放对象。当你调用 scheduledTimerWithTimeInterval ,如果这是一个重复计时器,它将保持对 target 的强引用。 ,防止目标被释放(至少在调用计时器的 invalidate 之前)。

考虑:

@implementation SecondViewController

- (void)viewDidLoad {
[super viewDidLoad];

[NSTimer scheduledTimerWithTimeInterval:3.0 target:self selector:@selector(logRetainCount) userInfo:nil repeats:YES];
}

- (void)logRetainCount {
NSLog(@"own retain count: %ld", CFGetRetainCount((__bridge CFTypeRef)self));
}

- (void)dealloc {
NSLog(@"view controller deallocated");
}

@end

当我推送到这个 View Controller 时,我在控制台上看到以下内容:

2016-09-15 15:50:10.279 MyApp[7777:159811] own retain count: 32016-09-15 15:50:13.340 MyApp[7777:159811] own retain count: 3

And when I pop that view controller off, I see:

2016-09-15 15:50:16.338 MyApp[7777:159811] own retain count: 22016-09-15 15:50:19.270 MyApp[7777:159811] own retain count: 2

Note, we do not see "view controller deallocated" appear in the console.

When I click on Xcode 8's "Debug Memory Graph" button, we can see that the timer is still keeping a strong reference to it:

timer

You ask:

  1. Why is dealloc being called if the object's retain count is not ever reaching 0?

It can't be. So, we must have multiple instances of the view controller involved here, one that has the repeating timer that isn't deallocated, and one without the timer, that is deallocated when its last strong reference is resolved. But whatever object is the target of the timer will still have a strong reference to it until the timer is invalidated, and it will not be deallocated until the timer has its invalidate called.

  1. Since dealloc is getting called, shouldn't, at the very least, the retain count be 1 since the NSTimer instance is holding onto it?

No, while the repeating timer is firing, its target cannot be deallocated. We must be talking about multiple instances of the view controller (or, unlike the example above, the target of the timer wasn't the view controller).

There are lots of ways to accidentally introduce additional instances of a view controller. For a random example (one that I've seen here on Stack Overflow more than once), consider that you did a segue between two view controllers, and had a prepareForSegue that did something like:

- (void)prepareForSegue:(UIStoryboardSegue *)segue sender:(id)sender {
SecondViewController *secondViewController = [self.storyboard instantiateViewControllerWithIdentifier:@"SecondViewController"];
secondViewController.property = @"foo";
}

这是不正确的,因为除了 segue 实例化的 View Controller (segue.destinationViewController)之外,上面的 prepareForSegue将创建另一个实例。在 prepareForSegue 中创建的那个一旦它超出范围就会被释放,但是由 segue 创建的那个不会被释放,因为在 viewDidLoad 中创建了重复计时器。 .

我并不是说这就是你所做的,但它说明了一种可能的方式来获得你所描述的行为。

但是,简而言之,不,在 ARC 中,一个仍然有任何强引用的对象将不会被释放。只有当最后一个剩余的强引用被移除时,它才会被释放。您问题中的代码不能单独产生您描述的行为。您必须处理一些额外的 View Controller 实例或类似的好奇。我可能会建议你创建一个 simple example重现了您描述的问题,因为您问题中的代码没有。还有其他事情正在发生。

关于ios - 是否可以在保留计数不为零的对象上调用 dealloc?,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/39520663/

25 4 0
Copyright 2021 - 2024 cfsdn All Rights Reserved 蜀ICP备2022000587号
广告合作:1813099741@qq.com 6ren.com