我有一个可以过滤和排序的UITableView
。当用户选择过滤器选项时,我尝试使用名为 liftUuidPredicate
的lazy 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
}
}