简体   繁体   中英

why do I get “Attempted to unregister unknown __weak variable” when copying an instance variable?

I noticed this today when playing with NSOutlineView and NSTableHeaderCell, but when this specific configuration is made, an error/warning(?) is printed:

objc[2774]: Attempted to unregister unknown __weak variable at 0x1016070d0. This is probably incorrect use of objc_storeWeak() and objc_loadWeak(). Break on objc_weak_error to debug.

here's the snippet:

class Foo: NSCell {
    weak var weak: NSView?

    override func copy(with zone: NSZone? = nil) -> Any {
        // according to NSCopying documentation:
        // If a subclass inherits NSCopying from its superclass and declares
        // additional instance variables, the subclass has to override copy(with:)
        // to properly handle its own instance variables, invoking the superclass’s implementation first.
        let copy = super.copy(with: zone) as! Foo

        // this produces "Attempted to unregister unknown __weak variable"
        copy.weak = self.weak

        return copy
    }
}

let view = NSView(frame: NSRect.zero)

let foo = Foo()
foo.weak = view

let copy = foo.copy() as! Foo

this also happens if I substitute NSCell with: NSEvent, NSImage, NSImageCell

but this doesn't happen to NSColor, NSDate, NSIndexPath

I started learning Swift without prior knowledge of Obj-C. could someone help me understand why this is? is it safe to ignore? who has the blame in this case?

This is a framework bug. It's easy to reproduce with the following crasher:

import Cocoa

class Cell: NSCell {
    var contents: NSString?

    override func copy(with zone: NSZone? = nil) -> Any {
        let newObject = super.copy(with: zone) as! Cell
        newObject.contents = contents
        return newObject
    }
}

func crash() {
    let cell = Cell()
    cell.contents = "hello world"
    cell.copy() // crashes while releasing the copied object
}

crash()

When you use a weak var instead, you get the error message that you showed.

My gut feeling is that there is something in the copy implementation of NSCell (and possibly of NSEvent and NSImage ) that does not handle subclassing for types that have non-trivial constructors. Accordingly, if you change let newObject = super.copy(...) with let newObject = Cell() , the crash is avoided. If your superclass's copy logic is simple enough, you should probably do that for now.

If you hit this problem, you should file a bug report separately of mine, but you can probably reuse my sample.

The technical post webpages of this site follow the CC BY-SA 4.0 protocol. If you need to reprint, please indicate the site URL or the original address.Any question please contact:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM