【问题标题】:Swift compile error, subclassing NSValue, using super.init(nonretainedObject:)Swift 编译错误,子类化 NSValue,使用 super.init(nonretainedObject:)
【发布时间】:2014-06-27 15:48:17
【问题描述】:

这段代码

class ID<T: AnyObject> : NSValue {
    init(baseObject: T) {
        super.init(nonretainedObject: baseObject)
    }
}

给出这个编译器错误:

error: must call a designated initializer of the superclass 'NSValue'
    super.init(nonretainedObject: baseObject)
    ^

我该如何摆脱它?

我想到的事情

我认为错误可能是因为 NSValue 初始化程序具有 AnyObject? 类型(注意:后缀 ?)。我尝试了各种类型的强制转换和[?!] 在某些地方后缀,但它没有修复任何问题。

另外,大概NSValue(nonretainedObject:) 必须调用指定的初始化器,对吧?

【问题讨论】:

    标签: swift nsvalue


    【解决方案1】:

    NSValue(nonretainedObject:) 不是指定的初始化器。 NSValue 引用中列出的唯一初始化程序(以及因此指定的初始化程序)是 NSValue(value:CConstVoidPointer, withObjCType type:CString)

    其他构造函数都是从类辅助方法派生的便利构造函数。

    你可以试试:

    init(baseObject: T) {
        super.init(bytes:&baseObject, withObjCType:"^v")
    }
    

    "^v" 是由 valueWithNonRetained.... 创建的 NSValue 返回的类型字符串。

    很遗憾,我没有想出合适的方法来将baseObject 作为 CConstVoidPointer 传递。

    除此之外,我能想到的最好的办法是包装 NSValue 而不是继承它:

    class ID<T:AnyObject> {
        let wrapped:NSValue
    
        init(baseObject:T) {
            wrapped = NSValue(nonretainedObject:baseObject)
        }
    }
    

    终于搞定了,不过有点难看,基本上加个方便的构造函数,把nonretainedObject构造函数包装起来,然后在你的子类中使用:

    extension NSValue {
        convenience init<T:AnyObject>(unretained:T) {
            self.init(nonretainedObject:unretained)
        }
    }
    
    
    class ID<T>:NSValue {
        convenience init<T:AnyObject>(unretained:T) {
            self.init(unretained:unretained)
        }
    }
    

    根据您实际尝试做的事情,单独的类别可能就足够了吗?

    【讨论】:

    • 目前,我在these Apple docs 中看到了init(nonretainedObject:)。文档似乎对他们是否指的是+value/-init 方法感到困惑。无论如何,您已经指出了一个好的解决方法。
    • 是的,这些文档非常明确地指出 init(bytes value: CConstVoidPointer, objCType type: Cstring) 是指定的初始化程序。现在,如果您能弄清楚如何将 baseObject 传递给您,那就太好了:)
    • IIUC,指定的初始化器是什么无关紧要,只要你链接到它。我认为所有NSValues 便利初始化程序都应该这样做,对吧?
    • 您最终必须从您的子类中调用 (a) 指定的初始化程序。为了方便起见,标记不是指定初始化程序的初始化程序也有一些限制,但我必须查明规则是什么。基本上编译器会告诉你把它标记为“方便”,你会这样做:)
    猜你喜欢
    • 1970-01-01
    • 1970-01-01
    • 2014-07-24
    • 1970-01-01
    相关资源
    最近更新 更多