NSArray 元素无法匹配 Swift Array 元素类型

Posted

技术标签:

【中文标题】NSArray 元素无法匹配 Swift Array 元素类型【英文标题】:NSArray element failed to match the Swift Array Element type 【发布时间】:2014-09-19 18:12:27 【问题描述】:

我有一个核心数据对象 (Order),它有一个方法可以返回另一个核心数据对象 (OrderWaypoint) 的数组。

func getOrderedWaypoints() -> [OrderWaypoint] 
    let nameDescriptor = NSSortDescriptor(key: "stop_number", ascending: true)
    let sorted: [OrderWaypoint] = self.waypoints.sortedArrayUsingDescriptors([nameDescriptor]) as [OrderWaypoint]
    return sorted

使用以下循环时,主目标中的一切都按预期工作

for waypoint in order.getOrderedWaypoints() 
   // do something

但是当我在我的测试目标中尝试完全相同的事情时

致命错误:NSArray 元素无法匹配 Swift Array 元素 输入

我已尝试转换值,但似乎无法使其正常工作。任何想法为什么它在主要目标而不是测试目标中有效?

编辑

好吧,进一步分解,当我尝试从数组中取出一个项目时,这个问题特别发生。

var orderedList: [OrderWaypoint] = order.getOrderedWaypoints()

for var i = 0; i < orderedList.count; i++ 
   var waypoint = orderedList[i]
   // do something

【问题讨论】:

创建 NSArray 并将其传递给 Swift 代码的代码在哪里? 我用方法定义更新了原始帖子。 order.waypoints 是 Core Data 中的 NSSet。我应用一个排序描述符来获取一个 NSArray 并向下转换为 [OrderWaypoint]。 你有没有得到这个工作?我处于类似的情况 - 以一种应该工作的方式使用 Core Data 子类,但我遇到了这个问题。 也有同样的问题。让这个工作顺利吗??? 当时我没有找到修复它的方法,而是改用 NSArray。我宁愿不这样做,但我没有时间回顾它。很抱歉下面的格式不好,但这是我们目前使用的。 func getOrderedWaypoints() -&gt; NSArray let nameDescriptor = NSSortDescriptor(key: "stop_number", ascending: true) let sorted = self.waypoints.sortedArrayUsingDescriptors([nameDescriptor]) return sorted 【参考方案1】:

您不能进行类型转换,因为sortedArrayUsingDescriptors 返回一个 NSArray,您需要将该数组中的所有元素复制到 Swift 类型数组中。

func getOrderedWaypoints() -> [OrderWaypoint] 
    let nameDescriptor = NSSortDescriptor(key: "stop_number", ascending: true)
    let sorted = [OrderWaypoint]()
    for elem in self.waypoints.sortedArrayUsingDescriptors([nameDescriptor]) 
        sorted.append(elem)
    
    return sorted

【讨论】:

【参考方案2】:

我通常不会在内存中进行所有排序,而是让那些获取相关数据的辅助方法直接从数据库中获取数据,例如:

var orderedWayPoints: [WayPoint] 
    let request = NSFetchRequest(entityName: "Waypoint")
    request.sortDescriptors = NSSortDescriptor(key: "stop_number", ascending: true)
    request.predicate = NSPredicate(format: "parent = %@", self)

    return try! managedObjectContext.executeFetchRequest(request)

关键是,我通常希望数据库完成排序数据的繁重工作,而不是代码。而且代码也不多。

【讨论】:

【参考方案3】:

最可能的原因是错误为真:self.waypoints 中的至少一个元素实际上不是OrderWaypoint。那里可能有其他类型可以响应相同的消息。你可能有一个OrderWaypoint 的超类(也许你在使用mogenerator 吗?这些实际上是_OrderWaypoint 对象吗?)你是否在调配对象以使它们谎报其真实类型? KVO 可以做到这一点。

这在您的测试目标中失败的事实增加了您在模拟这些对象的可能性。这可能吗?

我会首先仔细检查self.waypoints 的内容,以确保它确实包含您认为的内容。

【讨论】:

【参考方案4】:

它只发生在您的测试目标中的原因是它是与您的主应用程序不同的模块,因此您在每个模块中获得不同版本的 OrderWaypoint 类,Swift 认为它们是不同的类:App.OrderWaypointAppTest.OrderWaypoint.

我正在自己的项目中解决这个问题,当我有一个好的解决方案时我会更新:)

更新:对于所有 Swift 项目,我认为解决方案是从测试目标中删除您的非测试 .swift 文件,并将 @testable import YourAppModuleName 添加到您的 Swift 测试中。显然这是现代方法,无论如何都应该这样做。 (不过如果你的应用都是 Swift 的,你可能不会遇到这个问题。)

不过,这对我不起作用,因为我有需要访问我的 Swift 类的 Objective-C 编写的测试,而且我很难找到用于导入应用目标的 Swift 模块的 Objective-C 等效项。

我的解决方案是在 Objective-C 中重写问题代码,它不会进行如此严格的类型检查。就我而言,这很容易,因为有问题的函数位于最初在 Objective-C 中声明的类的扩展中,因此很容易将它们移过来。

更新 2: 一个略显卑鄙但更简单的解决方案是从测试目标中删除应用程序 Swift 文件,然后将测试目标中的标头搜索路径设置为指向 DerivedSources 文件夹来自 app 目标,并在需要它的 Objective-C 测试中包含 App-Swift.h 文件,而不是不再具有应用 Swift 类的 AppTest-Swift.h 文件,因为您刚刚将它们从测试目标。

【讨论】:

你当然不应该在测试目标中有源文件,但你不应该去jimmy头搜索路径。尤其是指向派生是可笑的。 好吧,我愿意接受替代方案。 Objective-C 源文件如何才能从另一个目标访问 Swift 类的定义? 都在here 中描述。很简单。对不起,如果我听起来像一个工具,我的源文件多年来一直在测试目标中,最终打破了它。 我以前浏览过那个页面。它讨论了导入框架,而不是从应用程序目标导入到测试目标。

以上是关于NSArray 元素无法匹配 Swift Array 元素类型的主要内容,如果未能解决你的问题,请参考以下文章

Firebase iOS Swift 致命错误:NSArray 元素无法匹配 Swift Array 元素类型

NSArray元素的原因无法与Swift数组元素类型匹配

Firestore NSArray 到 Swift.Array 匹配错误

Strange Down-casted Array 元素无法匹配 Swift 3 中的目标类型问题

Swift json 解析错误:无法将 NSCFConstantString 类型的值转换为 NSArray

Alamofire 4 请求返回 NSArray,无法弄清楚如何在 Swift 3 中使用 SwiftyJSON 进行解析