快速铸造泛型数组导致致命错误

问题描述:

我有一个充当BLL的类,封装了一个服务协议。该服务协议提供了一个SerializableObjectProtocol对象的列表。例如,我有User,它实现SerializedObjectProtocol快速铸造泛型数组导致致命错误

以下功能蒙上了SerializedObjectProtol阵列为User

public func Get() -> [T] 
{ 
    let result = self._service.Get() 

    return result as! [T] 
} 

其结果是,我收到以下错误:

array element cannot be bridged to Objective-C 

我知道该代码是容易出错的,因为如果对象不是T,则不会发生向下投射。因此,这里是我可以验证:在约束

  • 吨至实施SerializedObjectProtol即

    class DataLayer<T:SerializableObjectProtocol> 
    
  • T是类型用户。 result是一个用户数组。即[User]

  • 我可以解决这个问题,但我必须手动投射每个项目。其结果是,这工作完全正常:

    var returnArray = [T]() 
    
    for item in result 
    { 
        returnArray.append(item as! T) 
    } 
    
    return returnArray; 
    

我刚拿起斯威夫特的项目,它的经验,所以我已经限制。因此,我出去看看我正在尝试的是什么(将数组[S]转换为[T])。看起来如果数组是[Any]这是可能的。

这是在Swift中的有效操作吗?或者这种方式不可能。

通常是不可能直接的Any它所包含的类型的阵列之间铸造,因为Any的存储器中存有完全不同表示:sizeof(Any)不等于sizeof(User)!一个数组可能有320个字节的长度,但10个User只需要80个字节,这同样适用于任何协议。结论:您需要投射每一件物品。

也许不喜欢这样:

return results.map{ $0 as! User } 

,或者如果你不知道每一个项目是否是User,你只能返回User就像这样:

return results.flatMap{ $0 as? User } 

如果您仍然存在问题,请发布一些仍然会产生错误的最小代码,但如果没有实际的代码,很难理解代码的外观如何?

+0

这是goo d知道。非常感谢你!我看过有关[Any] - > [T]的文章,但互联网并不总是学习适当约定的最佳场所。 –

+0

注意:混合和匹配这样的铸造通常不是一个好主意。在这种情况下,绝对确定该对象是用户。该服务设置为返回需要序列化的服务的SerializableObjectProtocol,例如WebService,可以从一个对象中提取字段/值的字典。在这一点上,如果一个对象不是User,那么在逻辑链的某个地方就会发生一个错误。像这样有选择性地将对象集合处理为实体类,并打破协议所鼓励的松散耦合。 –

+0

@SergueiFedorov协议何时才能成为用户?一般来说,我认为如果你需要在你的(纯粹的)Swift代码中进行转换,那么你做错了什么,在用纯Swift编程时(没有ObjC,没有JSON等)我根本没有用过它们。 – Kametrixom