2017-06-22 33 views
0

我有一个可以过滤和排序的UITableView。当用户选择一个过滤器选项时,我试图使用名为liftUuidPredicatelazy var来构造谓词。用户的选择存储在UserDefaults但如果没有选择的过滤器,也不会在UserDefaults.logFilterLiftUuid()任何价值,这是导致我的应用程序错误崩溃:如何为NSPredicate创建一个可以返回零的惰性变量

NSInvalidArgumentException', reason: '*** -copyWithZone: cannot be sent to an abstract object of class NSPredicate: Create a concrete instance!

显然,我需要创建一个具体的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()可用的方法期望的格式和某种形式的参数(S)时,我希望这是没有断言这将不起作用。在guard let声明中,我也试过return NSPredicate(value: false),但是,正如我预期的那样,fetchRequest并没有返回任何记录。

我该如何做这项工作?

回答

0

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

的关键是从NSPredicateNSPredicate?和,而不是返回NSPredicate()回报nil如果guard无法改变的liftUuidPredicate类型。

我添加了一些锅炉板代码,使我的代码片段编译,所以你会想改变,因为你的需求决定。

`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 
    } 

} 
相关问题