NSManagedObject.entity () - неинициализирован - PullRequest
2 голосов
/ 10 октября 2019

У меня проблема с CoreData. У меня есть такая общая функция, которая выглядит так:

func fetchRequest<T : NSManagedObject>() -> NSFetchRequest<T>?
{
    let entity = T.entity()
    guard let entityName = entity.name else { return nil }
    let request = NSFetchRequest<T>(entityName: entityName)
    return request
}

Нет причин, по которым это не должно работать - и в большинстве случаев это без проблем. Однако иногда моя функция возвращает nil. Когда я отлаживаю его, я получаю самые интересные результаты:

(lldb) po entity
<uninitialized>

Это интересно, потому что NSManagedObject.entity() возвращает необязательное значение NSEntityDescription

Не существует правила относительно того, когда оно выходит из строя -например, когда я вызываю эту функцию 5 раз в цикле, она может сработать первые два раза, а затем потерпеть неудачу в третий раз. Никаких правил относительно класса сущностей тоже нет.

Я пробовал и кое-что еще.

extension NSManagedObject
{
    class func concreteFetchRequest<T>() -> NSFetchRequest<T>
    {
        let entityName = String(describing: self)
        return NSFetchRequest(entityName: entityName)
    }
}

В большинстве случаев это также работает, но иногда

po entityName
NSManagedObject

несмотря на использование бетоном NSManagedObject подкласс. Ошибка возникает, когда эта универсальная функция используется в ряде других универсальных функций, например:

func theTop()
{
    let instance : ConcreteNSManagedObjectSubclass = firstOrCreated() // "Entity description for entity name NSManagedObject not found"
}    

func firstOrCreated<T: NSManagedObject>() -> T
{
    let entity : T
    if let existingEntities() {
        // do stuff
    }
    // do other stuff
}

func existingEntities<T: NSManagedObject>() -> [T]?
{
    guard let request : NSFetchRequest<T> = fetchRequest() else 
    { return [] }
    // do stuff
}

func fetchRequest<T : NSManagedObject>() -> NSFetchRequest<T>?
{
    let entity = T.entity()
    guard let entityName = entity.name else { return nil }
    let request = NSFetchRequest<T>(entityName: entityName)
    return request
}

Однако, если я изменю код для создания NSFetchRequest в самом верху, прямо с ConcreteNSManagedObjectSubclass и передать его - он всегда работает.

func theTop()
{
    let fetchRequest : NSFetchRequest<ConcreteNSManagedObjectSubclass> = ConcreteNSManagedObjectSubclass.concreteFetchRequest()
    let instance : ConcreteNSManagedObjectSubclass = firstOrCreated(fetchRequest) // works fine
}

Это похоже на ошибку компилятора Swift, как будто он не может разрешить параметр T в конкретный тип, поэтому он возвращается к NSManagedObject вместо этого - но если бы это было так, это даже не должно компилироваться. Или я что-то не так делаю?

1 Ответ

0 голосов
/ 16 октября 2019

Пожалуйста, замените:

let request = NSFetchRequest<T>(entityName: entityName)

на:

let request = T.Type.fetchRequest() as NSFetchRequest<T>

или

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

в зависимости от того, что вам нравится.

...