在Swift中将任何类型转换为AnyObject

4

我有一个包含在字典中的对象,如下所示:

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

然后稍后我正在尝试将该对象用作按钮按下的目标:

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

And I get the error:

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

我猜我的问题在于将Any转换为AnyObject,这是否可能?请注意,我只是在猜测。
3个回答

3
任何类型都可以转换为任何对象类型。您可以使用 .unsafelyUnwrappedAny 转换为 AnyObject,无论它是类、结构体、枚举、整数、字符串等。
在下面的代码中,_change[.oldKey] 返回 Any,请按照以下代码将其解包并强制转换为 AnyObject
 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
}

我使用了KVO(键值观察)ObserveValue forKeyPath来接收[NSKeyValueChangeKey : Any]格式的变化通知。
我成功地从Any类型中检索出相应的CGPoint值,并将其转换为AnyObject,再转换为CGPoint


3

无法将AnyAnyObject进行任何降级转换,是的,您遇到的问题与Any无法转换为AnyObject有关。

Any可以表示任何类型(类、结构、枚举、整数、字符串等),而AnyObject只能表示引用类型(即类)。

为解决此问题,我认为您应该更改字典以存储AnyObject类型的值:

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

请注意,即使字典包含 AnyObject 值,它也可以存储以下类型:

  • 数字
  • 字符串
  • 数组
  • 字典

因为这些类型会自动转换为相应的 ObjC 类型(NSNumberNSArrayNSDictionary 等)。

如果你真的需要最大的灵活性,那么建议使用 NSDictionary - 但在这种情况下,值类型必须明确地封装在引用类型中(例如,在 NSNumber 中使用 int 等)。

@rintaro 的答案也是另一个不错的选择。


2

你不能将 Any 转换为 AnyObject,但是你 可以 将其转换为任何具体的类:

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

当然,如果dict["obj"]不是UIViewController类型,可能会导致运行时错误,因此需要更加安全的写法:

    if let target = dict["obj"] as? UIViewController {
        button.addTarget(target, action: "buttonPress:", forControlEvents: .TouchUpInside)
    }
    else {
        fatalError("dict[\"obj\"] is not UIViewController!")
    }

当然,最好使用您自己的子类,而不是UIViewController

在这两种情况下,如果dict["obj"]的类型不正确,代码就会出错。在第一种情况下,系统会准确地告诉您问题所在,在第二种情况下,代码将运行,而您将不知道为什么按钮无法工作。因此,我认为第一段代码更安全。 - Daniel T.
哦,我明白了,并且在这种情况下同意。 - rintaro
现在两段代码的作用基本相同,为什么要选择第二个更复杂的代码块而不是第一个更简单的呢?我仍然认为第一段代码块是更好的选择。(我最喜欢你的答案,但第一段比第二段更好。) - Daniel T.

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接