【问题标题】:CoreData NSPredicateCoreData NSPredicate
【发布时间】:2018-09-25 16:52:48
【问题描述】:

我将一个旧项目从 Swift 1 转换为使用 CoreData 的 Swift 4.2(在主要版本步骤中,均已成功构建)。

现在编译器在尝试执行此代码时会抛出以下错误:

let sortDescriptor = NSSortDescriptor(key: "dateModified", ascending: false)
let predicate = NSPredicate(format: "markAsDeleted == false")
if let itemInspections = item.inspections?.filtered(using: predicate).sortedArray(using: [sortDescriptor]) {
    label.text = "Items (\(itemInspections.count))"
}

错误:

2018-09-25 17:19:06.606722+0200 AppName[538:144354] -[_NSFaultingMutableSet filteredOrderedSetUsingPredicate:]:无法识别的选择器发送到实例 0x17063afc0 2018-09-25 17:19:06.607861+0200 AppName[538:144354] *** 由于未捕获的异常“NSInvalidArgumentException”而终止应用程序,原因:“-[_NSFaultingMutableSet filteredOrderedSetUsingPredicate:]:无法识别的选择器发送到实例 0x17063afc0”

*** 首先抛出调用堆栈: (0x18f5d6fd8 0x18e038538 0x18f5ddef4 0x18f5daf4c 0x18f4d6d2c 0x100126ce0 0x10015fa10 0x10015fc18 0x195ff9268 0x19575f884 0x19575a4ac 0x1956fc158 0x1928ec274 0x1928e0de8 0x1928e0ca8 0x19285c360 0x1928833c0 0x1956f17a0 0x18f5849a0 0x18f582628 0x18f582a74 0x18f4b2d94 0x190f1c074 0x195764130 0x100110cb4 0x18e4c159c) P>

libc++abi.dylib:以 NSException 类型的未捕获异常终止

任何指针将不胜感激。

【问题讨论】:

  • 您应该将谓词和排序描述符应用于获取请求对象,看起来您正在将它用于已从核心数据中获取的对象。
  • 我觉得这个问题可以帮到stackoverflow.com/questions/4490013/…

标签: ios swift core-data swift4.2


【解决方案1】:

强烈建议使用适当的谓词和排序描述符重新获取项目,而不是手动进行

代码假设有一个 NSManagedObject 子类 Inspectionitem 关系,并且由 item 表示的实体具有唯一属性 name

let sortDescriptor = NSSortDescriptor(key: "dateModified", ascending: false)
let predicate = NSPredicate(format: "item.name == %@ AND markAsDeleted == FALSE", item.name)
let fetchRequest : NSFetchRequest<Inspection> = Inspection.fetchRequest()
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
do {
    let itemInspections = try managedObjectContext.fetch(fetchRequest)
    label.text = "Items (\(itemInspections.count))"
} catch { print(error) }

如果您只需要过滤项目的数量,还有更高效的 API

let sortDescriptor = NSSortDescriptor(key: "dateModified", ascending: false)
let predicate = NSPredicate(format: "item.name == %@ AND markAsDeleted == FALSE", item.name)
let fetchRequest : NSFetchRequest<Inspection> = Inspection.fetchRequest()
fetchRequest.predicate = predicate
fetchRequest.sortDescriptors = [sortDescriptor]
do {
    let numberOfItemInspections = try managedObjectContext.count(for: fetchRequest)
    label.text = "Items (\(numberOfItemInspections))"
} catch { print(error) }

【讨论】:

    【解决方案2】:

    尽量避免实体属性的显式字符串,同时将false替换为正确的格式表达式:

    let sortDescriptor = NSSortDescriptor(key: "\#keyPath(YourClassHere.dateModified)", ascending: false)
    let predicate = NSPredicate(format: "\#keyPath(YourClassHere.markAsDeleted) == @%", NSNummber(value: false))
    if let itemInspections = item.inspections?.filtered(using: predicate).sortedArray(using: [sortDescriptor]) {
        label.text = "Items (\(itemInspections.count))"
    }
    

    【讨论】:

    • 你可以写== FALSENSNumber对象不是必须的。
    【解决方案3】:

    我最终将检查类型更改为 NSSet 并显式转换过滤的结果(使用:_)-> 像这样更改代码:

    let sortDescriptor = NSSortDescriptor(key: "dateModified", ascending: false)
    let predicate = NSPredicate(format: "markAsDeleted == false")        
    if let itemInspections = NSSet(set: (item.inspections?.filtered(using: predicate))!).sortedArray(using: [sortDescriptor]) as? [Inspection] {
        inspectionsCountLabel.text = "Inspections (\(itemInspections.count))"
    }
    

    感谢您的 cmets,他们为我指明了正确的方向!

    【讨论】:

      猜你喜欢
      • 2012-09-21
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 2011-11-06
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      • 1970-01-01
      相关资源
      最近更新 更多