Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Casting Any to AnyObject in Swift

Tags:

swift

I have an object contained within a Dictionary like so:

let dict:<String, Any> = ["obj": self]

Then later on I am trying to use that object as the target of a button press:

button.addTarget(dict["obj"], action: "buttonPress:", forControlEvents: .TouchUpInside)

And I get the error:

Type '(String, Any)' does not conform to protocol 'AnyObject'

I am guessing here my issue is trying to cast Any as AnyObject. Is this even possible?

like image 774
Jimmery Avatar asked Feb 11 '23 14:02

Jimmery


2 Answers

No downcasting from Any to AnyObject is not possible, and yes, the problem you have is about Any not convertible to AnyObject.

Any can represent any type (classes, structs, enums, ints, strings etc.), whereas AnyObject can represent reference types only (i.e. classes).

To solve the problem, I think you should change your dictionary to store values of AnyObject type:

let dict:<String, AnyObject> = ["obj": self]

Note that even if the dictionary contains AnyObject values, it can also store:

  • numbers
  • strings
  • arrays
  • dictionaries

because these types are automatically bridged to the corresponding objc types (NSNumber, NSArray, NSDictionary, etc.)

If you really need to have max flexibility, then I suggest using NSDictionary - but in that case value types must be explicitly boxed in reference types (i.e. int in NSNumber, etc.).

Also @rintaro's answer in another good option.

like image 89
Antonio Avatar answered Mar 06 '23 17:03

Antonio


Any to AnyObject is possible. You can unwrap Any to AnyObject by using .unsafelyUnwrapped of Any regardless it's classes, structs, enums, ints, strings etc.

Here _change[.oldKey] returns Any, unwrap and cast it to AnyObject as done in below code.

 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've used KVO ObserveValue forKeyPath to receive change in [NSKeyValueChangeKey : Any] format.
I successfully retrieved CGPoint values converted from Any to AnyObject then to CGPoint.

like image 33
Kiran Jasvanee Avatar answered Mar 06 '23 18:03

Kiran Jasvanee