奇怪的 ARC 问题未在 UIView 子类中释放 ivar

发布于 2024-12-28 11:49:11 字数 1779 浏览 3 评论 0原文

可能的重复:
为什么使用 ARC + NSZombieEnabled 时对象未释放

我目前在一个项目中遇到了一个非常奇怪的问题。简而言之,我有 ViewA ,它拥有 ViewBstrong 属性)。 ViewA 在其初始化程序中创建其 ViewB。这两个对象都是 UIView 的子类。

我已经重写了两者中的dealloc,并放置了一个日志行和一个断点来查看它们是否被击中。看起来 ViewAdealloc 被命中,但 ViewB 没有被命中。但是,如果我在 ViewAdealloc 中放入 self.viewB = nil ,那么它就会被命中。

所以基本上是这样的:

@interface ViewA : UIView
@property (nonatomic, strong) ViewB *viewB;
@end

@implementation ViewA

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.viewB = [[ViewB alloc] initWithFrame:self.bounds];
        [self addSubview:self.viewB];
    }
    return self;
}

- (void)dealloc {
    //self.viewB = nil; ///< Toggling this commented/uncommented changes if ViewB's dealloc gets called.
    NSLog(@"ViewA dealloc");
}

@end

我不明白的是为什么 nil-ing viewB out 会产生影响。如果有其他东西在 viewB 上,那么我是否在这里将其清零应该没有什么区别。而且它也不会对 ARC 添加的版本数量产生影响。

我似乎还无法在最小的测试用例中重现它,但我正在努力。不幸的是,我无法发布我看到的实际代码。不过,我不认为这是一个问题,因为更重要的是,将其清零不应该使我感到困惑。

任何人都可以看到我忽略的任何内容,或者提供有关在哪里寻找调试此问题的建议吗?

更新:

我发现了问题。看来只有当 NSZombieEnabled 设置为 YES 时才会出现问题。嗯,这完全是疯狂的,而且肯定是一个错误。据我所知,僵尸不应该影响它的工作方式。这些对象仍应通过 dealloc 方法。更重要的是,如果我在 ViewAdealloc 中清空 viewB ,它就会起作用,这真是太疯狂了。

Possible Duplicate:
Why is object not dealloc'ed when using ARC + NSZombieEnabled

I've got a very strange issue I'm seeing at the moment in a project. Put simply I have ViewA which owns ViewB (strong property). ViewA creates its ViewB in its initialiser. Both objects are subclasses of UIView.

I have overridden dealloc in both and put a log line and a break point to see if they get hit. It seems that ViewA's dealloc is being hit but not ViewB's. However if I put in a self.viewB = nil in the dealloc of ViewA then it is hit.

So basically it's something like this:

@interface ViewA : UIView
@property (nonatomic, strong) ViewB *viewB;
@end

@implementation ViewA

- (id)initWithFrame:(CGRect)frame {
    if (self = [super initWithFrame:frame]) {
        self.viewB = [[ViewB alloc] initWithFrame:self.bounds];
        [self addSubview:self.viewB];
    }
    return self;
}

- (void)dealloc {
    //self.viewB = nil; ///< Toggling this commented/uncommented changes if ViewB's dealloc gets called.
    NSLog(@"ViewA dealloc");
}

@end

What I can't understand is why nil-ing viewB out makes a difference. If something else is holding onto viewB then it should make absolutely no difference if I nil it out or not here. And it shouldn't make a difference to the number of releases that ARC adds in either.

I can't seem to reproduce it in a minimal test case as yet, but I'm working on it. And I can't post the actual code I'm seeing this in unfortunately. I don't see that being an issue though because it's more the point that nil-ing it out shouldn't make a difference that I am confused by.

Can anyone see anything I am overlooking or give advice about where to look for debugging this problem?

Update:

I've found the problem. It appears that it's only a problem when NSZombieEnabled is set to YES. Well that is entirely mad and has to be a bug surely. Zombies should not affect how this works as far as I know. The objects should still go through the dealloc method. And what's more, it's just mad that it works if I nil out viewB in ViewA's dealloc.

如果你对这篇内容有疑问,欢迎到本站社区发帖提问 参与讨论,获取更多帮助,或者扫码二维码加入 Web 技术交流群。

扫码二维码加入Web技术交流群

发布评论

需要 登录 才能够评论, 你可以免费 注册 一个本站的账号。

评论(1

岁吢 2025-01-04 11:49:11

我发现这似乎是 iOS 僵尸实现中的一个错误。考虑以下代码:

#import <Foundation/Foundation.h>

@interface ClassB : NSObject
@end

@implementation ClassB
- (id)init {
    if ((self = [super init])) {
    }
    return self;
}
- (void)dealloc {
    NSLog(@"ClassB dealloc");
}
@end

@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *b;
@end

@implementation ClassA
@synthesize b;
- (id)init {
    if ((self = [super init])) {
        b = [[ClassB alloc] init];
    }
    return self;
}
- (void)dealloc {
    NSLog(@"ClassA dealloc");
}
@end

int main() {
    ClassA *a = [[ClassA alloc] init];
    return 0;
}

应该输出:

ClassA dealloc
ClassB dealloc

但是将 NSZombieEnabled 设置为 YES 时,它输出:

ClassA dealloc

据我所知,这是一个错误。它似乎只发生在 iOS(模拟器和设备)上,而在为 Mac OS X 构建和运行时不会发生。我已经向 Apple 提交了雷达。

编辑:事实证明这个问题已经在这里得到了回答 - 为什么使用 ARC + NSZombieEnabled 时对象未释放 。在我发现真正的问题是什么后,设法找到了它。顺便说一句,这与ARC无关。

I've found that this appears to be a bug in the iOS implementation of zombies. Consider the following code:

#import <Foundation/Foundation.h>

@interface ClassB : NSObject
@end

@implementation ClassB
- (id)init {
    if ((self = [super init])) {
    }
    return self;
}
- (void)dealloc {
    NSLog(@"ClassB dealloc");
}
@end

@interface ClassA : NSObject
@property (nonatomic, strong) ClassB *b;
@end

@implementation ClassA
@synthesize b;
- (id)init {
    if ((self = [super init])) {
        b = [[ClassB alloc] init];
    }
    return self;
}
- (void)dealloc {
    NSLog(@"ClassA dealloc");
}
@end

int main() {
    ClassA *a = [[ClassA alloc] init];
    return 0;
}

That should output:

ClassA dealloc
ClassB dealloc

But with NSZombieEnabled set to YES, it outputs:

ClassA dealloc

As far as I can tell, this is a bug. It seems to only happen with iOS (both simulator and device) and does not happen when built and run for Mac OS X. I've filed a radar with Apple.

Edit: It turns out this has already been answered here - Why is object not dealloc'ed when using ARC + NSZombieEnabled . Managed to find it after I found out what the real problem was. It's nothing to do with ARC by the way.

~没有更多了~
我们使用 Cookies 和其他技术来定制您的体验包括您的登录状态等。通过阅读我们的 隐私政策 了解更多相关信息。 单击 接受 或继续使用网站,即表示您同意使用 Cookies 和您的相关数据。
原文