关于 iOS10 和 iOS11 中没有 `removeObserver:forKeyPath:` 的 KVO 不同行为
About KVO different behavior in iOS10 and iOS11 without `removeObserver:forKeyPath:`
有一次我在使用KVO的时候忘了调用"removeObserver:forKeyPath:"。在 iOS10 模拟器上,模拟器崩溃了。但是在 iOS11 模拟器上,一切正常。没有内存泄漏,也没有崩溃。
我很困惑为什么不调用 "removeObserver:forKeyPath:" 会在不同的 SDK 版本上导致不同的结果。
这里是演示代码:
#import <UIKit/UIKit.h>
@interface GSObject : NSObject
@end
@interface GSObject ()
@property (nonatomic, assign) NSInteger integer;
@end
@implementation GSObject
- (instancetype)init {
if (self = [super init]) {
[self addObserver:self forKeyPath:@"integer" options:NSKeyValueObservingOptionInitial context:nil];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void
*)context {
NSLog(@"%@",object);
}
@end
int main(int argc, char * argv[]) {
@autoreleasepool {
GSObject *object = [[GSObject alloc] init];
object = nil;
}
}
I'm confused why I didn't call "removeObserver:forKeyPath:" it shows different result on different sdk version.
那是因为不同的SDK版本不一样。他们的行为不同。这就是“不同”的意思。
请阅读发行说明,https://developer.apple.com/library/archive/releasenotes/Foundation/RN-Foundation/index.html :
Prior to 10.13 [and iOS 11], KVO would throw an exception if any observers were still registered after an autonotifying object's -dealloc
finished running.
有一次我在使用KVO的时候忘了调用"removeObserver:forKeyPath:"。在 iOS10 模拟器上,模拟器崩溃了。但是在 iOS11 模拟器上,一切正常。没有内存泄漏,也没有崩溃。
我很困惑为什么不调用 "removeObserver:forKeyPath:" 会在不同的 SDK 版本上导致不同的结果。
这里是演示代码:
#import <UIKit/UIKit.h>
@interface GSObject : NSObject
@end
@interface GSObject ()
@property (nonatomic, assign) NSInteger integer;
@end
@implementation GSObject
- (instancetype)init {
if (self = [super init]) {
[self addObserver:self forKeyPath:@"integer" options:NSKeyValueObservingOptionInitial context:nil];
}
return self;
}
- (void)observeValueForKeyPath:(NSString *)keyPath ofObject:(id)object
change:(NSDictionary<NSKeyValueChangeKey,id> *)change context:(void
*)context {
NSLog(@"%@",object);
}
@end
int main(int argc, char * argv[]) {
@autoreleasepool {
GSObject *object = [[GSObject alloc] init];
object = nil;
}
}
I'm confused why I didn't call "removeObserver:forKeyPath:" it shows different result on different sdk version.
那是因为不同的SDK版本不一样。他们的行为不同。这就是“不同”的意思。
请阅读发行说明,https://developer.apple.com/library/archive/releasenotes/Foundation/RN-Foundation/index.html :
Prior to 10.13 [and iOS 11], KVO would throw an exception if any observers were still registered after an autonotifying object's
-dealloc
finished running.