103

在 Swift 2 中,以下代码正在运行:

let request = NSFetchRequest(entityName: String)

但在 Swift 3 中它给出了错误:

无法推断通用参数“ResultType”

因为NSFetchRequest现在是泛型类型。在他们的文件中,他们写道:

let request: NSFetchRequest<Animal> = Animal.fetchRequest

所以如果我的结果类是例如Level我应该如何正确请求?

因为这不起作用:

let request: NSFetchRequest<Level> = Level.fetchRequest
4

10 回答 10

134
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?
}

重点是删除字符串常量的使用。

于 2016-06-14T12:18:47.047 回答
56

我想我这样做是为了让它工作:

let request:NSFetchRequest<NSFetchRequestResult> = NSFetchRequest(entityName: "Level")

至少它从数据库中保存和加载数据。

但感觉这不是一个合适的解决方案,但它现在有效。

于 2016-06-14T12:14:35.567 回答
33

我发现在 3.0 中工作的最简单的结构如下:

let request = NSFetchRequest<Country>(entityName: "Country")

其中数据实体类型是国家。

但是,在尝试创建 Core Data BatchDeleteRequest 时,我发现此定义不起作用,您似乎需要使用以下表单:

let request: NSFetchRequest<NSFetchRequestResult> = Country.fetchRequest()

即使 ManagedObject 和 FetchRequestResult 格式应该是等效的。

于 2016-06-15T22:58:36.407 回答
13

以下是一些通用的 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)")
    }
}

假设 Contact 有一个 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()
于 2016-10-15T07:47:18.437 回答
6

这是迁移到 Swift 3.0 的最简单方法,只需添加<Country>

(经过测试和工作)

let request = NSFetchRequest<Country>(entityName: "Country")
于 2016-10-19T07:36:18.663 回答
1

Swift 3.0 这应该可以。

let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate
于 2017-12-26T08:33:36.917 回答
0

我也有“ResultType”无法推断错误。一旦我重建将每个实体的 Codegen 设置为“类定义”的数据模型,它们就会清除。我在这里做了一个简短的文章,并附有分步说明:

在 Xcode 8 和 Swift 3 中寻找关于修改后的 NSPersistentContainer 的清晰教程

“重建”是指我创建了一个具有新条目和属性的新模型文件。有点乏味,但它的工作!

于 2016-09-23T04:02:12.937 回答
0

到目前为止对我最有效的是:

let request = Level.fetchRequest() as! NSFetchRequest<Level>
于 2016-09-30T09:57:57.577 回答
0

我遇到了同样的问题,我通过以下步骤解决了它:

  • 选择您的 xcdatamodeld 文件并转到数据模型检查器
  • 选择您的第一个实体并转到 Section 类
  • 确保选择了 Codegen“类定义”。
  • 删除所有生成的实体文件。你不再需要它们了。

在这样做之后,我不得不删除/重写所有出现的 fetchRequest,因为 XCode 似乎以某种方式与代码生成的版本混淆了。

高温高压

于 2016-12-23T08:29:43.357 回答
0
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()
    
}
于 2021-06-10T08:38:00.890 回答