I am converting an app from Objective-C to Swift 2.0 and while converting an NSView
-subclass, I am getting an error while trying to store a weak
back-reference from a CALayer
to the ActionViewItemInternal
which is needed so that the layer drawing code can access the item data. I want to use a weak
reference in order to avoid a retain-cycle (item object retains layer so layer needs a weak reference back to the item object).
class WeakReference {
weak var reference: AnyObject?
init(reference: AnyObject) {
self.reference = reference
}
}
class ActionView: NSView {
// Used to store an item in ActionView.items
private class ActionViewItemInternal {
var actionViewItem: ActionViewItem
var layer: CALayer
...
init(withItem actionViewItem: ActionViewItem) {
self.actionViewItem = actionViewItem
let layer = CALayer()
// !!!!!!!!!!!!!!!!!!!!!!!!!!
// other init and error here:
// !!!!!!!!!!!!!!!!!!!!!!!!!!
layer.setValue(value: WeakReference(reference: self), forKey: "ActionViewItem")
self.layer = layer
}
}
var items: [ActionViewItem] = [ActionViewItem]()
...
}
Where ActionItemView
is defined as:
@objc protocol ActionViewItem {
var name: String { get set }
var icon: NSImage { get set }
var enabled: Bool { get set }
}
I am getting the error:
ActionView.swift:73:19: Cannot invoke 'setValue' with an argument list of type '(value: WeakReference, forKey: String)'
Xcode version: Xcode 7.0 beta 1. Deployment targets tried: 10.9, 10.10 and 10.11.
EDIT: I have tried using NSValue
, as per @rickster's suggestion, but the error remains:
layer.setValue(value: NSValue(nonretainedObject: self), forKey: "ActionViewItem")
ActionView.swift:72:19: Cannot invoke 'setValue' with an argument list of type '(value: NSValue, forKey: String)'
The setValue(_:forKey:)
method requires an ObjC object for the value — you're passing an instance of a pure Swift class. If you make your WeakReference
class either annotated with @objc
or inherit from NSObject
that call should succeed.
However, you don't need your own class for this purpose anyway... The NSValue
method valueWithNonretainedObject
does the same thing.
Oh, and on closer inspection: you're using an extra argument label in your call. It should be like setValue(myvalue, forKey: mykey)
.