如何将类型应用于 NSFetchRequest 实例?
How to apply the type to a NSFetchRequest instance?
在 Swift 2 中,以下代码有效:
let request = NSFetchRequest(entityName: String)
但在 Swift 3 中出现错误:
Generic parameter "ResultType" could not be inferred
因为 NSFetchRequest
现在是泛型。他们在他们的文件中写道:
let request: NSFetchRequest<Animal> = Animal.fetchRequest
所以如果我的结果 class 例如 Level
我应该如何正确请求?
因为这不起作用:
let request: NSFetchRequest<Level> = Level.fetchRequest
我想我是这样做的:
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")
至少它从数据库中保存和加载数据。
但感觉这不是一个合适的解决方案,但目前有效。
let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest()
或
let request: NSFetchRequest<Level> = Level.fetchRequest()
取决于你想要的版本。
您必须指定泛型类型,否则方法调用是不明确的。
第一个版本是为 NSManagedObject
定义的,第二个版本是为每个使用扩展名的对象自动生成的,例如:
extension Level {
@nonobjc class func fetchRequest() -> NSFetchRequest<Level> {
return NSFetchRequest<Level>(entityName: "Level");
}
@NSManaged var timeStamp: NSDate?
}
重点是删除字符串常量的使用。
我发现在 3.0 中工作的最简单的结构如下:
let request = NSFetchRequest<Country>(entityName: "Country")
其中数据实体类型是国家/地区。
然而,在尝试创建 Core Data BatchDeleteRequest 时,我发现这个定义不起作用,您似乎需要使用以下形式:
let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()
尽管 ManagedObject 和 FetchRequestResult 格式应该是等价的。
我也有"ResultType"无法推断的错误。一旦我重建数据模型,将每个实体的代码生成设置为 "Class Definition",它们就会被清除。我在这里写了一篇带有分步说明的简短文章:
Looking for a clear tutorial on the revised NSPersistentContainer in Xcode 8 with Swift 3
"rebuilt" 我的意思是我创建了一个包含新条目和属性的新模型文件。有点乏味,但很管用!
到目前为止最适合我的是:
let request = Level.fetchRequest() as! NSFetchRequest<Level>
以下是一些可能会回答您的问题的通用 CoreData 方法:
import Foundation
import Cocoa
func addRecord<T: NSManagedObject>(_ type : T.Type) -> T
{
let entityName = T.description()
let context = app.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
let record = T(entity: entity!, insertInto: context)
return record
}
func recordsInTable<T: NSManagedObject>(_ type : T.Type) -> Int
{
let recs = allRecords(T.self)
return recs.count
}
func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func query<T: NSManagedObject>(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
if let predicate = search
{
request.predicate = predicate
}
if let sortDescriptors = multiSort
{
request.sortDescriptors = sortDescriptors
}
else if let sortDescriptor = sort
{
request.sortDescriptors = [sortDescriptor]
}
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func deleteRecord(_ object: NSManagedObject)
{
let context = app.managedObjectContext
context.delete(object)
}
func deleteRecords<T: NSManagedObject>(_ type : T.Type, search: NSPredicate? = nil)
{
let context = app.managedObjectContext
let results = query(T.self, search: search)
for record in results
{
context.delete(record)
}
}
func saveDatabase()
{
let context = app.managedObjectContext
do
{
try context.save()
}
catch
{
print("Error saving database: \(error)")
}
}
假设联系人有一个 NSManagedObject 设置,如下所示:
class Contact: NSManagedObject
{
@NSManaged var contactNo: Int
@NSManaged var contactName: String
}
这些方法可以通过以下方式使用:
let name = "John Appleseed"
let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name
let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %@", name))
for contact in contacts
{
print ("Contact name = \(contact.contactName), no = \(contact.contactNo)")
}
deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %@", name))
recs = recordsInTable(Contact.self)
print ("Contacts table has \(recs) records")
saveDatabase()
这是迁移到 Swift 3.0 的最简单方法,只需添加 <Country>
(测试和工作)
let request = NSFetchRequest<Country>(entityName: "Country")
我遇到了同样的问题,我通过以下步骤解决了它:
- Select 您的 xcdatamodeld 文件并转到数据模型检查器
- Select 您的第一个实体并转到第 class
部分
- 确保选择了 Codegen "Class Definition"。
- 删除所有生成的实体文件。你不再需要它们了。
之后我不得不 remove/rewrite 所有出现的 fetchRequest 因为 XCode 似乎以某种方式与代码生成的版本混淆了。
HTH
Swift 3.0 这应该可以。
let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func loadItemsCategory() {
let request: NSFetchRequest<Category> = Category.fetchRequest()
do {
categoryArray = try context.fetch(request)
} catch {
print(error)
}
tableView.reloadData()
}
在 Swift 2 中,以下代码有效:
let request = NSFetchRequest(entityName: String)
但在 Swift 3 中出现错误:
Generic parameter "ResultType" could not be inferred
因为 NSFetchRequest
现在是泛型。他们在他们的文件中写道:
let request: NSFetchRequest<Animal> = Animal.fetchRequest
所以如果我的结果 class 例如 Level
我应该如何正确请求?
因为这不起作用:
let request: NSFetchRequest<Level> = Level.fetchRequest
我想我是这样做的:
let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")
至少它从数据库中保存和加载数据。
但感觉这不是一个合适的解决方案,但目前有效。
let request: NSFetchRequest<NSFetchRequestResult> = Level.fetchRequest()
或
let request: NSFetchRequest<Level> = Level.fetchRequest()
取决于你想要的版本。
您必须指定泛型类型,否则方法调用是不明确的。
第一个版本是为 NSManagedObject
定义的,第二个版本是为每个使用扩展名的对象自动生成的,例如:
extension Level {
@nonobjc class func fetchRequest() -> NSFetchRequest<Level> {
return NSFetchRequest<Level>(entityName: "Level");
}
@NSManaged var timeStamp: NSDate?
}
重点是删除字符串常量的使用。
我发现在 3.0 中工作的最简单的结构如下:
let request = NSFetchRequest<Country>(entityName: "Country")
其中数据实体类型是国家/地区。
然而,在尝试创建 Core Data BatchDeleteRequest 时,我发现这个定义不起作用,您似乎需要使用以下形式:
let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()
尽管 ManagedObject 和 FetchRequestResult 格式应该是等价的。
我也有"ResultType"无法推断的错误。一旦我重建数据模型,将每个实体的代码生成设置为 "Class Definition",它们就会被清除。我在这里写了一篇带有分步说明的简短文章:
Looking for a clear tutorial on the revised NSPersistentContainer in Xcode 8 with Swift 3
"rebuilt" 我的意思是我创建了一个包含新条目和属性的新模型文件。有点乏味,但很管用!
到目前为止最适合我的是:
let request = Level.fetchRequest() as! NSFetchRequest<Level>
以下是一些可能会回答您的问题的通用 CoreData 方法:
import Foundation
import Cocoa
func addRecord<T: NSManagedObject>(_ type : T.Type) -> T
{
let entityName = T.description()
let context = app.managedObjectContext
let entity = NSEntityDescription.entity(forEntityName: entityName, in: context)
let record = T(entity: entity!, insertInto: context)
return record
}
func recordsInTable<T: NSManagedObject>(_ type : T.Type) -> Int
{
let recs = allRecords(T.self)
return recs.count
}
func allRecords<T: NSManagedObject>(_ type : T.Type, sort: NSSortDescriptor? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func query<T: NSManagedObject>(_ type : T.Type, search: NSPredicate?, sort: NSSortDescriptor? = nil, multiSort: [NSSortDescriptor]? = nil) -> [T]
{
let context = app.managedObjectContext
let request = T.fetchRequest()
if let predicate = search
{
request.predicate = predicate
}
if let sortDescriptors = multiSort
{
request.sortDescriptors = sortDescriptors
}
else if let sortDescriptor = sort
{
request.sortDescriptors = [sortDescriptor]
}
do
{
let results = try context.fetch(request)
return results as! [T]
}
catch
{
print("Error with request: \(error)")
return []
}
}
func deleteRecord(_ object: NSManagedObject)
{
let context = app.managedObjectContext
context.delete(object)
}
func deleteRecords<T: NSManagedObject>(_ type : T.Type, search: NSPredicate? = nil)
{
let context = app.managedObjectContext
let results = query(T.self, search: search)
for record in results
{
context.delete(record)
}
}
func saveDatabase()
{
let context = app.managedObjectContext
do
{
try context.save()
}
catch
{
print("Error saving database: \(error)")
}
}
假设联系人有一个 NSManagedObject 设置,如下所示:
class Contact: NSManagedObject
{
@NSManaged var contactNo: Int
@NSManaged var contactName: String
}
这些方法可以通过以下方式使用:
let name = "John Appleseed"
let newContact = addRecord(Contact.self)
newContact.contactNo = 1
newContact.contactName = name
let contacts = query(Contact.self, search: NSPredicate(format: "contactName == %@", name))
for contact in contacts
{
print ("Contact name = \(contact.contactName), no = \(contact.contactNo)")
}
deleteRecords(Contact.self, search: NSPredicate(format: "contactName == %@", name))
recs = recordsInTable(Contact.self)
print ("Contacts table has \(recs) records")
saveDatabase()
这是迁移到 Swift 3.0 的最简单方法,只需添加 <Country>
(测试和工作)
let request = NSFetchRequest<Country>(entityName: "Country")
我遇到了同样的问题,我通过以下步骤解决了它:
- Select 您的 xcdatamodeld 文件并转到数据模型检查器
- Select 您的第一个实体并转到第 class 部分
- 确保选择了 Codegen "Class Definition"。
- 删除所有生成的实体文件。你不再需要它们了。
之后我不得不 remove/rewrite 所有出现的 fetchRequest 因为 XCode 似乎以某种方式与代码生成的版本混淆了。
HTH
Swift 3.0 这应该可以。
let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate
let context = (UIApplication.shared.delegate as! AppDelegate).persistentContainer.viewContext
func loadItemsCategory() {
let request: NSFetchRequest<Category> = Category.fetchRequest()
do {
categoryArray = try context.fetch(request)
} catch {
print(error)
}
tableView.reloadData()
}