如何为可以返回 nil 的 NSPredicate 创建一个惰性变量



我有一个可以过滤和排序的UITableView。当用户选择过滤器选项时,我尝试使用名为 liftUuidPredicatelazy var来构造谓词。用户的选择存储在UserDefaults中,但如果没有选择筛选器,则UserDefaults.logFilterLiftUuid()中将没有任何值,这会导致我的应用崩溃并显示错误:

NSInvalidArgumentException', reason: '*** -copyWithZone: 不能 发送到类 NSPredicate 的抽象对象:创建一个具体 实例!

显然,我需要创建一个 NSPredicate 的具体实例,但是当没有谓词时我不知道该怎么做。

// throws the 'Create a concrete instance' error
lazy var liftUuidPredicate: NSPredicate = {
    guard let liftUuid = UserDefaults.logFilterLiftUuid() else { return NSPredicate() }
    return NSPredicate(format: "uuid = %@", liftUuid)
}()
// fetchedResultsController
func fetchLiftEvents() -> NSFetchedResultsController<NSFetchRequestResult> {
  let moc = stack.managedObjectContext
  let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "LiftEvent")
  fetchRequest.predicate = liftUuidPredicate
  if let sortBy = UserDefaults.logSortSelection() {fetchRequest.sortDescriptors = [NSSortDescriptor(key: sortBy, ascending: false)]}
  fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
  do {
       try fetchedResultsController!.performFetch()
      } catch {
       fatalError("Unable to fetch Lift Events: (error)")
    }
  return fetchedResultsController!
}

NSPredicate()可用的方法期望一种格式和某种形式的参数,当我希望没有谓词时,这些格式和参数将不起作用。在guard let语句中,我也尝试了return NSPredicate(value: false)但是,正如我所料,fetchRequest随后没有返回任何记录。

我怎样才能做到这一点?

NSPredicate是一个抽象类。 您不能有 NSPredicate() ,您必须使用所需的信息实例化它才能获得具体实例。

关键是将liftUuidPredicate的类型从NSPredicate更改为NSPredicate?,而不是在guard失败时返回NSPredicate() nil

我添加了一些样板代码来编译我的代码片段,因此您需要根据需要进行更改。

`extension UserDefaults {
    class func logFilterLiftUuid() -> String? {
        return "bar"
    }
    class func logSortSelection() -> String? {
        return "bar"
    }
}
class Foo {
    let stack = NSFetchedResultsController<NSManagedObject>()
    var fetchedResultsController = NSFetchedResultsController<NSFetchRequestResult>()
    // throws the 'Create a concrete instance' error
    lazy var liftUuidPredicate: NSPredicate? = {
        guard let liftUuid = UserDefaults.logFilterLiftUuid() else { return nil }
        return NSPredicate(format: "uuid = %@", liftUuid)
    }()
    // fetchedResultsController
    func fetchLiftEvents() -> NSFetchedResultsController<NSFetchRequestResult> {
        let moc = stack.managedObjectContext
        let fetchRequest = NSFetchRequest<NSFetchRequestResult>(entityName: "LiftEvent")
        fetchRequest.predicate = liftUuidPredicate
        if let sortBy = UserDefaults.logSortSelection() {fetchRequest.sortDescriptors = [NSSortDescriptor(key: sortBy, ascending: false)]}
        fetchedResultsController = NSFetchedResultsController(fetchRequest: fetchRequest, managedObjectContext: moc, sectionNameKeyPath: nil, cacheName: nil)
        do {
            try fetchedResultsController.performFetch()
        } catch {
            fatalError("Unable to fetch Lift Events: (error)")
        }
        return fetchedResultsController
    }
}

最新更新