Как применить тип к экземпляру NSFetchRequest?


в Swift 2 работал следующий код:

let request = NSFetchRequest(entityName: String)

но в Swift 3 это дает ошибку:

общий параметр "ResultType" не может быть выведен

, потому что NSFetchRequest теперь является общим типом. В своих документах они написали следующее:

let request: NSFetchRequest<Animal> = Animal.fetchRequest

так что если мой класс результат например Level как надо правильно просить?

потому что это не работает:

let request: NSFetchRequest<Level> = Level.fetchRequest
9 92

9 ответов:

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

все дело в том, чтобы удалить использование строковых констант.

Я думаю, что я получил это работает путем делать это:

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

по крайней мере она сохраняет и загружает данные из базы данных.

но кажется, что это не правильное решение, но оно работает сейчас.

самая простая структура, которую я нашел, которая работает в 3.0, выглядит следующим образом:

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

где тип объекта данных-страна.

при попытке создать ядро данных BatchDeleteRequest, однако, я обнаружил, что это определение не работает, и кажется, что вам нужно будет пойти с формой:

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

хотя форматы ManagedObject и FetchRequestResult должны быть эквивалентны.

вот некоторые общие методы 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")

Я тоже имел "параметром resulttype, имеющим значение" не может быть выведено ошибок. Они очистились после того, как я перестроил модель данных, установив код каждого объекта в "определение класса". Я сделал краткую запись с пошаговыми инструкциями здесь:

Ищу четкий учебник по пересмотренному NSPersistentContainer в Xcode 8 с Swift 3

под "перестроенным" я имею в виду, что я создал новый файл модели с новыми записями и атрибутами. Немного утомительно, но это сработало!

что работало лучше для меня до сих пор было:

let request = Level.fetchRequest() as! NSFetchRequest<Level>

У меня была такая же проблема и я решил ее следующим образом:

  • Выберите файл xcdatamodeld и перейдите в Инспектор модели данных
  • выберите свой первый объект и перейдите в раздел class
  • убедитесь, что выбран параметр Codegen "определение класса".
  • удалите все созданные файлы сущностей. Они тебе больше не нужны.

после этого мне пришлось удалить / переписать все вхождения fetchRequest, как кажется XCode чтобы как-то смешаться с кодовой версией.

HTH

Swift 3.0 это должно работать.

let request: NSFetchRequest<NSFetchRequestResult> = NSManagedObject.fetchRequest()
request.entity = entityDescription(context)
request.predicate = predicate