У меня проблема с 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
вместо этого - но если бы это было так, это даже не должно компилироваться. Или я что-то не так делаю?