如何为可以返回 nil 的 NSPredicate 创建惰性 var

Posted

技术标签:

【中文标题】如何为可以返回 nil 的 NSPredicate 创建惰性 var【英文标题】:How do I create a lazy var for an NSPredicate that can return nil 【发布时间】:2017-06-22 17:50:03 【问题描述】:

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

NSInvalidArgumentException',原因:'*** -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 然后没有返回任何记录。

我怎样才能做到这一点?

【问题讨论】:

【参考方案1】:

NSPredicate 是一个抽象类。您不能拥有NSPredicate(),您必须使用所需的信息对其进行实例化以获取具体实例。

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

我添加了一些样板代码来使我的 sn-p 编译,因此您可以根据需要进行更改。

`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
    


【讨论】:

以上是关于如何为可以返回 nil 的 NSPredicate 创建惰性 var的主要内容,如果未能解决你的问题,请参考以下文章

如何为这种请求创建正确的 NSPredicate?

如何为 CoreData 多对多关系编写 NSPredicate

如何为 CoreData 中包含 NSArray 的二进制数据创建 NSPredicate?

核心数据,NSPredicate,任何 key.path == nil

NSPredicate 搜索具有 nil 值的连接表

如何为文本字段设置条件。文本?