首页
学习
活动
专区
圈层
工具
发布
社区首页 >问答首页 >Remove观察者:forKeyPath: in Foundation崩溃

Remove观察者:forKeyPath: in Foundation崩溃
EN

Stack Overflow用户
提问于 2015-05-11 10:17:32
回答 3查看 8.3K关注 0票数 19

从Xcode中的“crash”部分检索的以下崩溃日志有一些问题。只有少数设备受此崩溃报告的影响。

我已经分析了这个问题,但我想这是苹果框架上的一个bug。但我找不到复制它的方法。

这里有一个类似的讨论:清除观察者:forKeyPath中的崩溃帮助:

有什么暗示吗?

线程0名称:线程0崩溃: 0基础 0x23507591 _NSKeyValueReplaceObservationInfoForObject + 69 (NSKeyValueObserving.m:1166) 1基金会 0x23506fe7 -NSObject(NSKeyValueObserverRegistration) _removeObserver:forProperty:+ 327 (NSKeyValueObserving.m:1552) 2基金会 0x23506b03 -NSObject(NSKeyValueObserverRegistration)远程观察员:forKeyPath:+ 163 (NSKeyValueObserving.m:1696) 3基金会 0x235069a7 -NSObject(NSKeyValueObserverRegistration) Remove观察者:forKeyPath:上下文:+ 219 (NSKeyValueObserving.m:1663) 4 ApplicationName 0x0002e233 -Supervisor RemoveObject观察者:forKeyPath:+ 115 (Supervisor.m:344)

removeObjectObserver:forKeyPath:在哪里

代码语言:javascript
复制
- (void) removeObjectObserver:(id)object forKeyPath:(NSString *)keyPath { 

    @try {        
        [object removeObserver:self forKeyPath:keyPath context:PrivateKVOContext];
    
    } @catch (NSException *exception) { }
}
EN

回答 3

Stack Overflow用户

发布于 2015-06-02 09:58:24

必须特别注意使用Observers in Objective-C:不要将相同的观察者倍数时间添加到同一个对象的属性中,如果存在这样的参数,则将删除包装起来:

代码语言:javascript
复制
  if ([self observationInfo]) {
        @try {
            [self removeObserver:self forKeyPath:keyPath];
        }
        @catch (NSException *exception) {}
    }

您正在经历崩溃,因为您试图删除两倍的观察者,或您正在删除一个不存在的观察者。

您应该以这种方式添加observers

代码语言:javascript
复制
[yourObject addObserver:self forKeyPath:keypath options:NSKeyValueObservingOptionNew|NSKeyValueObservingOptionInitial context:nil/yourContext];

编辑:您可以删除已经释放的对象上的观察者,从而导致此崩溃。

代码语言:javascript
复制
  if (object && [self observationInfo]) {
    @try {
                [self removeObserver:self forKeyPath:keyPath];
            }
            @catch (NSException *exception) {}
}
票数 8
EN

Stack Overflow用户

发布于 2015-06-25 07:36:26

通常,你有一个象牙塔,你可以知道你是否反对的键盘,观察在这个时候。像@property(.)BOOL textFieldTextObserving;以及添加/删除观察方法应该在添加/删除之前检查此属性,以避免添加/删除观察者两次。如果有许多观察对象和键盘(以@(BOOL)作为对象,-identifiers作为键),您也可以使用-identifiers。

无论如何,使用@try-exception做事情并不是推荐的目标-C方式。苹果公司的文档上说:

"You should not use a try-catch block in place of standard programming checks for Objective-C methods. In the case of an NSArray, for example, you should always check the array’s count to determine the number of items before trying to access an object at a given index. The objectAtIndex: method throws an exception if you make an out-of-bounds request so that you can find the bug in your code early in the development cycle—you should avoid throwing exceptions in an app that you ship to users." https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/ProgrammingWithObjectiveC/ErrorHandling/ErrorHandling.html

票数 5
EN

Stack Overflow用户

发布于 2019-12-21 17:13:31

现在给出答案为时已晚,但我也面临着同样的问题。所以我决定给别人写这个。

注意:崩溃的主要原因是在添加之前尝试删除一个观察者。

我已经创建了一些扩展来帮助您安全地移除观察者。斯威夫特5号

您现在可以在添加之前删除它,而不会崩溃。请确保您还删除了deinit中的观察者。

使用:

代码语言:javascript
复制
objectToObserve.safeRemoveObserver(self, keyPath: "myDate", context: &myContext)

扩展:

代码语言:javascript
复制
extension NSRegularExpression {

convenience init(_ pattern: String) {
    do {
        try self.init(pattern: pattern)
    } catch {
        preconditionFailure("Illegal regular expression: \(pattern).")
    }
}

func matches(_ string: String) -> Bool {
    let range = NSRange(location: 0, length: string.utf16.count)
    return firstMatch(in: string, options: [], range: range) != nil
   }
 }

extension NSObject {

func safeRemoveObserver(_ observer: NSObject, keyPath: String, context: inout Int) {
    let result = checkIfAlreadyAdded(keyPath: keyPath, context: &context)

    if result {
        removeObserver(observer, forKeyPath: keyPath, context: &context)
    }
}

fileprivate func address(_ o: UnsafeRawPointer) -> Int {
    return Int(bitPattern: o)
}

fileprivate func checkIfAlreadyAdded(keyPath: String, context: inout Int) -> Bool {

    guard self.observationInfo != nil else { return false }

    let info = Unmanaged<AnyObject>
           .fromOpaque(self.observationInfo!)
           .takeUnretainedValue()

    let contextStr = NSString(format: "%p", address(&context))
    let infoStr = info.description ?? ""

    let regex = NSRegularExpression("\(keyPath).*[a-z].*\(contextStr)")
    let result = regex.matches(infoStr)

    return result
  }
}
票数 1
EN
页面原文内容由Stack Overflow提供。腾讯云小微IT领域专用引擎提供翻译支持
原文链接:

https://stackoverflow.com/questions/30165085

复制
相关文章

相似问题

领券
问题归档专栏文章快讯文章归档关键词归档开发者手册归档开发者手册 Section 归档