无法执行存储在Array [Any]中的对象的方法

问题描述 投票:0回答:2

我想在数组中存储不同类型的对象。以下程序只是最低限度的演示。在anyArray中:[Any]存储Object1的一个实例。 print语句打印出预期的对象类型。在以下行中,存储对象类型的测试返回true。这意味着,在运行时,正确的对象类型是已知的,并且每件事情似乎都很好。

    class Object1 {
        var name = "Object1"
    }

    var anyArray:[Any] = [Object1()]
    print("\(type(of: anyArray[0]))")
    let testResult = anyArray[0] is Object1
    print("Test result:\(testResult)")
    //print("Name:\((anyArray[0]).name)")

Console output:
   Object1
   Test result:true

但是,如果我尝试打印出对象的name属性,我会从编辑器中收到一条错误消息:

Value of type 'Any' has no member 'name'

好吧,在编译时,对象的类型是未知的。这就是编译器抱怨的原因。如何告诉编译器可以访问存储对象的属性?

ios swift casting any anyobject
2个回答
2
投票

差异来自与类型检查的区别:

  • 运行时,或
  • 编译时间

is运算符在运行时检查表达式是否可以转换为指定的类型。 type(of:)在运行时检查确切的类型,而不考虑子类。

anyArray[0].name没有编译,因为类型Any没有name属性。

如果你确定anyArray[0]Object1,你可以使用downcast运算符as!

print("\((anyArray[0] as! Object1).name)")

要在运行时检查来自anyArray的元素是否可以是Object1,请使用可选绑定,使用条件转换运算符as?

  • 如果让: if let object = anyArray[0] as? Object1 { print(object.name) }
  • 或者如果要在范围的其余部分中使用该对象,请使用guard语句: guard let object = anyArray[0] as? Object1 else { fatalError("The first element is not an Object1") } print(object.name)

如果数组中的所有对象都具有name属性,并且您不想重复执行可选绑定的所有环节,则使用协议。您的代码将如下所示:

protocol Named {
    var name: String {get set}
}

class Object1: Named {
    var name = "Object1"
}

var anyArray:[Named] = [Object1()]
print("\(type(of: anyArray[0]))")
let testResult = anyArray[0] is Object1
print("Test result:\(testResult)")
print("Name:\(anyArray[0].name)")

请注意,anyArray现在是Named对象的数组,并且Object1符合Named协议。

要了解有关协议的更多信息,请查看here


2
投票

你的对象仍然是Any类型。你刚检查它是否可以是Object1类型,但你没有投出它。如果你想将对象作为Object1,你需要施放它。

此外,如果多个类可以具有名称,则需要使用qvxswpoi,如@vadian在评论中提到的并将其转换为该协议。

Protocol

编辑:“我想在数组中存储不同类型的对象”。如果您拥有的所有对象都不符合协议,则标记为正确的解决方案将不起作用。

© www.soinside.com 2019 - 2024. All rights reserved.