Как применить тип к экземпляру NSFetchRequest?
В Swift 2 работал следующий код:
let request = NSFetchRequest(entityName: String)
но в Swift 3 он дает ошибку:
Общий параметр «ResultType» не может быть выведен
потому что NSFetchRequest
теперь является общим типом. В своих документах они написали:
let request: NSFetchRequest = Animal.fetchRequest
поэтому, если мой class результатов – это, например, Level
как я должен правильно запросить?
Потому что это не работает:
let request: NSFetchRequest = Level.fetchRequest
- Расшифровать схему базы данных
- Как создать базу данных mysql с несколькими арендаторами
- Что такое EOF на языке программирования C?
- Как я могу уменьшить код привязки RadioButton?
- Как моделировать систему голосования «любит» с помощью MongoDB
- NoSql vs Реляционная firebase database
- Хранить изображения в базе данных MongoDB
- Динамические данные, связывающие данные
let request: NSFetchRequest = Level.fetchRequest()
или
let request: NSFetchRequest = Level.fetchRequest()
в зависимости от того, какую версию вы хотите.
Вы должны указать общий тип, потому что иначе вызов метода неоднозначен.
Первая версия определена для NSManagedObject
, вторая версия создается автоматически для каждого объекта с использованием расширения, например:
extension Level { @nonobjc class func fetchRequest() -> NSFetchRequest { return NSFetchRequest (entityName: "Level"); } @NSManaged var timeStamp: NSDate? }
Все дело в том, чтобы удалить использование строковых констант.
Я думаю, что я работал, делая это:
let request:NSFetchRequest = NSFetchRequest(entityName: "Level")
по крайней мере, он сохраняет и загружает данные из базы данных.
Но похоже, что это не правильное решение, но оно работает пока.
Простейшая структура, которую я нашел в 3.0, выглядит следующим образом:
let request = NSFetchRequest(entityName: "Country")
где объект данных Тип – страна.
Однако, пытаясь создать базовый пакет данных DataDeleteRequest, я обнаружил, что это определение не работает, и кажется, что вам нужно перейти к форме:
let request: NSFetchRequest = Country.fetchRequest()
хотя форматы ManagedObject и FetchRequestResult должны быть эквивалентными.
Вот некоторые общие методы CoreData, которые могут ответить на ваш вопрос:
import Foundation import Cocoa func addRecord(_ 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 (_ type : T.Type) -> Int { let recs = allRecords(T.self) return recs.count } func allRecords (_ 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 (_ 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 (_ 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 для NDS предусмотрена настройка 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, просто добавьте
(проверено и проработано)
let request = NSFetchRequest(entityName: "Country")
У меня также был «ResultType» не может быть выведенных ошибок. Они очистились, как только я перестроил модель данных, задав Codegen каждого объекта «Определение classа». Я сделал краткую запись с пошаговыми инструкциями здесь:
В поисках четкого руководства по пересмотренному NSPersistentContainer в Xcode 8 с Swift 3
Под «rebuilt» я имею в виду, что я создал новый файл модели с новыми записями и атрибутами. Немного утомительно, но это сработало!
То, что работало лучше всего для меня до сих пор, было:
let request = Level.fetchRequest() as! NSFetchRequest
У меня была такая же проблема, и я решил ее с помощью следующих шагов:
- Выберите файл xcdatamodeld и перейдите к инспектору модели данных
- Выберите свой первый объект и перейдите в раздел Класс
- Убедитесь, что выбрано Codegen «Определение classа».
- Удалите все созданные вами файлы Entity. Они вам больше не нужны.
После этого мне пришлось удалить / переписать все вхождения fetchRequest, поскольку XCode, похоже, каким-то образом смешивается с кодированной версией.
НТН
Swift 3.0 Это должно сработать.
let request: NSFetchRequest = NSManagedObject.fetchRequest() request.entity = entityDescription(context) request.predicate = predicate