Swift AnyObject - 将一个协议数组向下转型为 [AnyObject]

3
你如何将协议实例的数组向下转换为 AnyObject?我尝试了下面代码示例中的一些较为合理的想法。
protocol Nameable : class {
    var name: String { get }
}

class Person: Nameable {
    var name: String

    init(name: String)
    {
        self.name = name
    }
}

class Example {

    func setArray(array: [AnyObject]?, forKey: String)
    {
        print("hello world")
    }
}

var personOne = Person(name: "Evan")
var personTwo = Person(name: "Brian")

var array: [ Nameable ] = [ personOne, personTwo ]

var anotherArray = array.map({ $0 as AnyObject })    // OMG gross!
var yetAnotherArray = array as [ AnyObject ]         // Nope.
var evenYetAnotherArray = array as? [ AnyObject ]    // Nope.
var omgThisIsAnArray = Array<AnyObject>(array)       // Ha ha, srsly. Nope.

var myExample = Example()
myExample.setArray(anotherArray, forKey: "Named")

就我个人而言,setArray(_ anArray: [AnyObject]?, forKey aKey: String)方法的签名来自于苹果的NSUbiquitousKeyValueStore类,所以我无法对其进行重构以实现类型安全。


如果一个对象符合AnyObject,但它的类型更加明确,那么不需要将对象强制转换为AnyObject以匹配方法签名。在你的情况下 - 正如Eric在他的答案中提到的那样 - 问题在于NSUbiquitousKeyValueStore仅支持属性列表兼容类型。 - vadian
2个回答

4

虽然不完美,但如果协议和类都带有 @objc 标记(且类是 NSObject 的子类),这个方法可以解决问题:

@objc protocol Nameable: class {
    var name: String { get }
}

@objc class Person: NSObject, Nameable {
    var name: String
    init(name: String) {
        self.name = name
    }
}

...

var array: [Nameable] = [personOne, personTwo]
let array2 = array as [AnyObject] // ✓

1
谢谢!关键在于AnyObject被注释为@objc,而我的协议没有。因此,无法进行强制转换是有道理的。 - edelaney05

0

这并不是直接回答你的问题,但我认为这不会像你期望的那样工作。

从 NSUbiquitousKeyValueStore setArray: 的文档中可以看到:

一个数组,其内容可以以属性列表格式存储。换句话说,数组中的对象必须是以下类型之一:NSNumberNSStringNSDateNSDataNSArrayNSDictionary。数组及其内容的总大小(以字节为单位)不得超过每个键的大小限制。

你试图放入的数据不属于上述任何一种类型,我猜你会遇到问题。

像这样的代码可以正常工作:

import UIKit // For String<->NSString bridging

protocol Nameable : class  {
    var name: String { get }
}

class Person: Nameable {
    var name: String

    init(name: String)
    {
        self.name = name
    }
}

class Example {

    func setArray(array: [AnyObject]?, forKey: String)
    {
        print("hello world")
    }
}

var personOne = Person(name: "Evan")
var personTwo = Person(name: "Brian")

var array: [ Nameable ] = [ personOne, personTwo ]

var nameArray = array.map({ $0.name }) // Now [String]

var myExample = Example()
myExample.setArray(nameArray, forKey: "Named")

或者您可以以其他方式序列化您的Swift对象,以将它们转换为支持的类之一。


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