如何为可以 return nil 的 NSPredicate 创建惰性变量
How do I create a lazy var for an NSPredicate that can return nil
我有一个UITableView
可以过滤和排序。当用户选择一个过滤器选项时,我试图使用一个名为 liftUuidPredicate
的 lazy var
来构造谓词。用户的选择存储在 UserDefaults
中,但如果没有选择过滤器,UserDefaults.logFilterLiftUuid()
中将没有任何值,这会导致我的应用程序崩溃并出现错误:
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()
的可用方法需要一种格式和某种形式的参数,当我不希望有谓词时,它们将不起作用。在 guard let
语句中,我也尝试了 return NSPredicate(value: false)
但是,正如我所料,fetchRequest 然后没有返回任何记录。
我怎样才能完成这项工作?
NSPredicate
是一个摘要 class。您不能拥有 NSPredicate()
,您必须使用所需信息对其进行实例化以获得具体实例。
关键是将 liftUuidPredicate
的类型从 NSPredicate
更改为 NSPredicate?
而不是 returning NSPredicate()
return nil
如果 guard
失败。
我添加了一些样板代码来编译我的代码片段,因此您需要根据需要更改它。
`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
}
}
我有一个UITableView
可以过滤和排序。当用户选择一个过滤器选项时,我试图使用一个名为 liftUuidPredicate
的 lazy var
来构造谓词。用户的选择存储在 UserDefaults
中,但如果没有选择过滤器,UserDefaults.logFilterLiftUuid()
中将没有任何值,这会导致我的应用程序崩溃并出现错误:
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()
的可用方法需要一种格式和某种形式的参数,当我不希望有谓词时,它们将不起作用。在 guard let
语句中,我也尝试了 return NSPredicate(value: false)
但是,正如我所料,fetchRequest 然后没有返回任何记录。
我怎样才能完成这项工作?
NSPredicate
是一个摘要 class。您不能拥有 NSPredicate()
,您必须使用所需信息对其进行实例化以获得具体实例。
关键是将 liftUuidPredicate
的类型从 NSPredicate
更改为 NSPredicate?
而不是 returning NSPredicate()
return nil
如果 guard
失败。
我添加了一些样板代码来编译我的代码片段,因此您需要根据需要更改它。
`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
}
}