Casting Anyone to AnyObject in Swift
I have an object contained in a dictionary, for example:
let dict:<String, Any> = ["obj": self]
Then later I try to use this object as the target of the button:
button.addTarget(dict["obj"], action: "buttonPress:", forControlEvents: .TouchUpInside)
And I am getting the error:
Type '(String, Any)' does not conform to protocol 'AnyObject'
I guess my problem here is to use Any
both AnyObject
. Is it possible?
source to share
Disconnecting from Any
to is AnyObject
not possible, and yes, the problem you have is about Any
not converting to AnyObject
.
Any
can represent any type (classes, structures, enumerations, ints, strings, etc.), whereas AnyObject
can only represent reference types (i.e. classes).
To solve the problem, I think you should change the dictionary to store values ββlike AnyObject
:
let dict:<String, AnyObject> = ["obj": self]
Note that even if a dictionary contains values AnyObject
, it can also store:
- numbers
- strings
- arrays
- dictionaries
because these types are automatically connected to the respective types objc ( NSNumber
, NSArray
, NSDictionary
etc.)
If you really want the most flexibility, I suggest using NSDictionary
, but in this case, the value types should be explicitly labeled in reference types (i.e. int
in NSNumber
, etc.).
Also @rintaro answers in another good variation.
source to share
Any
before AnyObject
. You can expand Any
to AnyObject
using .unsafelyUnwrapped
of Any
no matter what classes, structs, enums, ints, strings, etc.
Here it _change[.oldKey]
returns Any
, expands and discards it on AnyObject
, as is done in the code below.
override public func observeValue(forKeyPath keyPath: String?, of object: Any?, change: [NSKeyValueChangeKey : Any]?, context: UnsafeMutableRawPointer?) {
guard let oldKey = (_change[.oldKey].unsafelyUnwrapped as AnyObject).cgPointValue else {
return
}
guard let newKey = (_change[.newKey].unsafelyUnwrapped as AnyObject).cgPointValue else {
return
}
print(oldKey)
print(newKey)
}
extension NSKeyValueChangeKey {
public static let newKey: NSKeyValueChangeKey
public static let oldKey: NSKeyValueChangeKey
}
I used KVO ObserveValue forKeyPath
to get the format changes [NSKeyValueChangeKey : Any]
.
I have successfully retrieved the CGPoint
values ββconverted from Any
to AnyObject
, then to CGPoint
.
source to share
You can not throw Any
up AnyObject
, but may transfer it to any particular class:
button.addTarget(dict["obj"] as UIViewController, action: "buttonPress:", forControlEvents: .TouchUpInside)
Of course this can lead to a runtime error if dict["obj"]
not UIViewController
, so make it more secure:
if let target = dict["obj"] as? UIViewController {
button.addTarget(target, action: "buttonPress:", forControlEvents: .TouchUpInside)
}
else {
fatalError("dict[\"obj\"] is not UIViewController!")
}
And of course it's better to use your own subclass instead of UIViewController
.
source to share