Swift 2.0: Cannot invoke 'setValue' with an argument list of

1.8k views Asked by At

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)'
1

There are 1 answers

2
rickster On BEST ANSWER

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).