代码之家  ›  专栏  ›  技术社区  ›  westsider

-observeValueForKeyPath:ofObject:change:context:消息已接收但未处理

  •  27
  • westsider  · 技术社区  · 14 年前

    我对KVO比较陌生,所以很有可能我违反了一些基本规则。我正在使用核心数据。

            *** Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: '<CGImage 0x276fc0>: An -observeValueForKeyPath:ofObject:change:context: message was received but not handled.
    Key path: measurementDescriptor
    Observed object: <MeasurementPointer: 0x8201640> (entity: MeasurementPointer; id: 0x8200410 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementPointer/p75> ; data: {
        measurementDescriptor = "0x260fd0 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementDescriptor/p22>";
    })
    Change: {
        kind = 1;
        new = "<MeasurementDescriptor: 0x262530> (entity: MeasurementDescriptor; id: 0x260fd0 <x-coredata://EBEE0687-D67D-4B03-8C95-F4C60CFDC20F/MeasurementDescriptor/p22> ; data: {\n    measurementName = Temperature;\n    measurementUnits = \"\\U00b0C\";\n    sortString = nil;\n})";
    }
    Context: 0x0'
    *** Call stack at first throw:
    (
        0   CoreFoundation                      0x30897ed3 __exceptionPreprocess + 114
        1   libobjc.A.dylib                     0x3002f811 objc_exception_throw + 24
        2   CoreFoundation                      0x30897d15 +[NSException raise:format:arguments:] + 68
        3   CoreFoundation                      0x30897d4f +[NSException raise:format:] + 34
        4   Foundation                          0x34a13779 -[NSObject(NSKeyValueObserving) observeValueForKeyPath:ofObject:change:context:] + 60
        5   Foundation                          0x349b6acd NSKeyValueNotifyObserver + 216
        6   Foundation                          0x349b6775 NSKeyValueDidChange + 236
        7   Foundation                          0x349ae489 -[NSObject(NSKeyValueObserverNotification) didChangeValueForKey:] + 76
        8   CoreData                            0x3165b577 _PF_ManagedObject_DidChangeValueForKeyIndex + 102
        9   CoreData                            0x3165ac51 _sharedIMPL_setvfk_core + 184
        10  CoreData                            0x3165dc83 _svfk_0 + 10
        11  SPARKvue                            0x000479f1 -[MeasurementViewController doneAction:] + 152
        12  CoreFoundation                      0x3083f719 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
        13  UIKit                               0x31eb1141 -[UIApplication sendAction:to:from:forEvent:] + 84
        14  UIKit                               0x31f08315 -[UIBarButtonItem(UIInternal) _sendAction:withEvent:] + 92
        15  CoreFoundation                      0x3083f719 -[NSObject(NSObject) performSelector:withObject:withObject:] + 24
        16  UIKit                               0x31eb1141 -[UIApplication sendAction:to:from:forEvent:] + 84
        17  UIKit                               0x31eb10e1 -[UIApplication sendAction:toTarget:fromSender:forEvent:] + 32
        18  UIKit                               0x31eb10b3 -[UIControl sendAction:to:forEvent:] + 38
        19  UIKit                               0x31eb0e05 -[UIControl(Internal) _sendActionsForEvents:withEvent:] + 356
        20  UIKit                               0x31eb1453 -[UIControl touchesEnded:withEvent:] + 342
        21  UIKit                               0x31eafddd -[UIWindow _sendTouchesForEvent:] + 368
        22  UIKit                               0x31eaf757 -[UIWindow sendEvent:] + 262
        23  UIKit                               0x31eaa9ff -[UIApplication sendEvent:] + 298
        24  UIKit                               0x31eaa337 _UIApplicationHandleEvent + 5110
        25  GraphicsServices                    0x31e4504b PurpleEventCallback + 666
        26  CoreFoundation                      0x3082cce3 __CFRUNLOOP_IS_CALLING_OUT_TO_A_SOURCE1_PERFORM_FUNCTION__ + 26
        27  CoreFoundation                      0x3082cca7 __CFRunLoopDoSource1 + 166
        28  CoreFoundation                      0x3081f56d __CFRunLoopRun + 520
        29  CoreFoundation                      0x3081f277 CFRunLoopRunSpecific + 230
        30  CoreFoundation                      0x3081f17f CFRunLoopRunInMode + 58
        31  GraphicsServices                    0x31e445f3 GSEventRunModal + 114
        32  GraphicsServices                    0x31e4469f GSEventRun + 62
        33  UIKit                               0x31e51123 -[UIApplication _run] + 402
        34  UIKit                               0x31e4f12f UIApplicationMain + 670
        35  SPARKvue                            0x000031ff main + 70
        36  SPARKvue                            0x000031b4 start + 40
    )
    terminate called after throwing an instance of 'NSException'
    Program received signal:  “SIGABRT”.
    

    引发这一切的是:

    [[self measurementPointer] setMeasurementDescriptor:descriptor];
    

    鉴于此,

    [[meterDisplay measurementPointer] addObserver:self 
                forKeyPath:@"measurementDescriptor"
                options:NSKeyValueObservingOptionNew
                context:nil];
    

    其他对象(模型对象和控制器对象)引用MeasurementPointers。MeasurementPointer引用MeasurementDescriptor。许多对象都想知道MeasurementPointer何时开始引用新的/不同的MeasurementDescriptor。例如,这样的更改可能会导致图形显示的轴发生更改。或者,在上面的代码中,可能会导致仪表显示显示不同的样本(来自选定的样本集)。

    我认为最根本的问题是CGImage接收到了一个不适合它的消息。。。不幸的是,这是间歇性的,所以我还没有找到触发它的模式。

    5 回复  |  直到 14 年前
        1
  •  41
  •   Felixyz    13 年前

    你有一个对象被解除锁定,并且没有停止观察另一个对象。走过你所有的 -addObserver... 打电话确认他们和 -removeObserver... 至少在 -dealloc 可能是在 -viewDidUnload 取决于您的应用程序结构。

        2
  •  9
  •   Sunil Sharma Tapas Palui    6 年前

    observeValueForKeyPath 方法到 super ,但我没有注册为变更观察员。 Apple docs 观察值分叉路径 如果它实现了 ."

    我的办法是改变:

    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context {
      if ([keyPath isEqualToString:kPropertyThatChanges]) {
        ...
      }
      [super observeValueForKeyPath:keyPath ofObject:object change:change context:context];
    }
    

    致:

    - (void)observeValueForKeyPath:(NSString *)keyPath
                          ofObject:(id)object
                            change:(NSDictionary *)change
                           context:(void *)context {
      if ([keyPath isEqualToString:kPropertyThatChanges]) {
        ...
      }
    }
    

    斯威夫特:

    func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if (keyPath == kPropertyThatChanges) {
        }
        super.observeValue(forKeyPath: keyPath, of: object, change: change, context: context)
    }
    To:
    func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
        if (keyPath == kPropertyThatChanges) {
        }
    }
    
        3
  •  3
  •   devios1    11 年前

    我遇到这个问题时,无意中把目标作为观察者(而不是自我)传入,就像这样:

    [self.someView addObserver:self.someView forKeyPath:@"key" options:0 context:nil];
    

    这个错误消息对识别这一点毫无帮助,所以我想我会发布,以防其他人做同样的事情。

        4
  •  1
  •   neowinston    13 年前

    我也有同样的问题,但在我的情况下,我观察到了不同的背景。然后我把所有的内容都放在同一个上下文中,崩溃就消失了。我希望这对某人有帮助。

        5
  •  1
  •   Lance Samaria    6 年前

    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) 对被观察到的键槽做些实际的事情。

    下面是Swift版本的一个例子。将观察者添加到 viewDidLoad 把它们移进去 deinit :

    lazy var firstNameTextField: UITextField = {
        let textField = UITextField()
        // configure your textField
        return textField
    }()
    
    lazy var lastNameTextField: UITextField = {
        let textField = UITextField()
        // configure your textField
        return textField
    }()
    
    override func viewDidLoad() {
        super.viewDidLoad()
    
        // 1. add your observers here
        firstNameTextField.addObserver(self, forKeyPath: "text", options: [.old, .new], context: nil)
        lastNameTextField.addObserver(self, forKeyPath: "text", options: [.old, .new], context: nil)
    }
    
    // 2. ***IMPORTANT you must add this function or it will crash***
    override func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
    
        if keyPath == "text" {
            print("do something when the textField's text your observing changes")
        }
    }
    
     // 3. remove them in deinit
    deinit {
        firstNameTextField.removeObserver(self, forKeyPath: "text", context: nil)
        lastNameTextField.removeObserver(self, forKeyPath: "text", context: nil)
        print("DEINIT")
    }
    
    推荐文章