问题
This code
class ID<T: AnyObject> : NSValue {
init(baseObject: T) {
super.init(nonretainedObject: baseObject)
}
}
gives this compiler error:
error: must call a designated initializer of the superclass 'NSValue'
super.init(nonretainedObject: baseObject)
^
How do I get rid of this?
Things I thought of
I thought the error might be because the NSValue
initializer has an AnyObject?
type (Note well: postfix ?
). I tried various flavors of casting and [?!]
postfixing in places, and it fixed nothing.
Also, presumably NSValue(nonretainedObject:)
must call the designated initializer, right?
回答1:
NSValue(nonretainedObject:)
isn't a designated initializer. The only initializer listed in the NSValue reference (and hence the designated initializer) is NSValue(value:CConstVoidPointer, withObjCType type:CString)
The other constructors are all convenience constructors derived from class helper methods.
You might try:
init(baseObject: T) {
super.init(bytes:&baseObject, withObjCType:"^v")
}
"^v" is the type string returned by an NSValue created with valueWithNonRetained....
Unfortunately, I'm not coming up with an appropriate way to pass baseObject
as a CConstVoidPointer.
Barring that, the best thing I can come up with is to wrap NSValue instead of subclassing it:
class ID<T:AnyObject> {
let wrapped:NSValue
init(baseObject:T) {
wrapped = NSValue(nonretainedObject:baseObject)
}
}
Finally got something to work, but it's a little bit ugly, basically add a convenience constructor that wraps the nonretainedObject constructor and then use that in your subclass:
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)
}
}
Depending on what you're actually trying to do the category alone might be sufficient?
来源:https://stackoverflow.com/questions/24455907/swift-compile-error-subclassing-nsvalue-using-super-initnonretainedobject