iOS: KVO内存泄漏?

4

注意: 我发布这篇文章是为了其他可能遇到同样问题的开发人员提供参考。

为什么我在使用这段代码时会出现内存泄漏:

@interface SPWKThing : NSObject
@property (strong, nonatomic) NSArray *things;
@end

@implementation SPWKThing {
    BOOL _isKVORegistered;
}

- (id)init
{
    self = [super init];
    if (self) {
        NSLog(@"initing SPWKThing");
        [self registerKVO];
    }
    return self;
}

- (void)didChangeValueForKey:(NSString *)key {
    if ([key isEqualToString:@"things"]) {
        NSLog(@"didChangeValueForKey: things have changed!");
    }
}

#pragma mark - KVO
- (void)registerKVO
{
    if (!_isKVORegistered) {
        NSLog(@"Registering KVO, and things is %@", _things);
        [self addObserver:self forKeyPath:@"things" options:0 context:NULL];
        _isKVORegistered = YES;
    }
}

- (void)unregisterKVO
{
    if (_isKVORegistered) {
        NSLog(@"Unregistering KVO");
        [self removeObserver:self forKeyPath:@"things"];
        _isKVORegistered = NO;
    }
}

- (void)dealloc
{
    NSLog(@"SPWKThing dealloc");
    [self unregisterKVO];
}

@end

@implementation SPWKViewController

- (void)viewDidLoad
{
    [super viewDidLoad];
    [self runDemo];
}

- (void)runDemo
{
    SPWKThing *thing = [[SPWKThing alloc] init];
    thing.things = @[@"one", @"two", @"three"];
    thing = nil;
}

@end

我的输出结果是:

initing SPWKThing
Registering KVO, and things is (null)
didChangeValueForKey: things have changed!

dealloc 没有被调用?为什么?我在 runDemo 的最后一行设置了 thing = nil

在此处查看演示项目:https://github.com/jfahrenkrug/KVOMemoryLeak


为什么你要监听自己的变化?只需要将响应setThings变化的代码放在某个地方即可...除非这个问题是用来讨论的练习... - Tim Reddy
如果您在unregisterKVO中设置断点会发生什么?在您的实现中使用BOOL是我以前从未做过的...通常我会在.m文件中使用类扩展来放置私有iVars...(即:@interface SPWKThing() {BOOL _isKVORegistered;} @end) - Tim Reddy
@TimReddy 这只是一个“讨论练习” :) 基本上我分享了我的发现,即在不调用super的情况下重写didChangeValueForKey:会导致内存泄漏。关于BOOL:https://dev59.com/Smox5IYBdhLWcg3w95E9#8853683 - Johannes Fahrenkrug
如果删除所有的KVO代码会发生什么?你的dealloc会被调用吗? - Merlevede
@Merlevede 是的。如果从未调用 addObserver:forKeyPath:options:context:,那么对象将被正确释放。 - Johannes Fahrenkrug
1个回答

3

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接