2017-06-16 64 views
2

当我的应用程序第一次启动时,我做了一些第一次安装配置,它使用CoreData API和JSON文档中的数据为我的SQLLite数据库播种。检索实体名称时崩溃?

我是这样做的,首先从我的核心数据堆栈中获取对管理对象上下文的引用,然后调用执行JSON配置的方法。然后我打电话给:

....(JSON conversion).... 

context.perform { 
_ = Exercise.insert(into: context, name: exerciseName, category: categoryNumber, equipment: equipment, skill: "", primaryMuscle: primaryMuscle, otherMuscles: otherMuscles, info: exerciseDescription, image1: exerciseImage1, image2: exerciseImage2) 
    } 

在每次迭代中,当我通过JSON对象循环时,它会保持每个对象。

用于插入对象的方法是这样的:

public static func insert(into context: NSManagedObjectContext, name: String, category: Int16, equipment: String?, skill: String?, primaryMuscle: String?, otherMuscles: String?, info: String?, image1: String?, image2: String?) -> Exercise { 
    let exercise: Exercise = context.insertObject() 
    exercise.name = name 
    exercise.category = category 
    exercise.info = info 
    exercise.primaryMuscle = primaryMuscle 
    exercise.otherMuscles = otherMuscles 
    exercise.equipment = equipment 
    exercise.skill = skill 

    if image1 != nil { 
     exercise.image1Path = image1 
    } 

    if image2 != nil { 
     exercise.image2Path = image2 
    } 

    return exercise 
} 

然后我伸出的NSManagedObjectContext ...

extension NSManagedObjectContext { 
public func insertObject<Object: NSManagedObject>() -> Object where Object: Managed { 
    guard let obj = NSEntityDescription.insertNewObject(forEntityName: Object.entityName, into: self) as? Object else { fatalError("Wrong object type") } 
    return obj 
} 
} 

这是我的我的 “托管” 协议的声明:

public protocol Managed: class, NSFetchRequestResult { 
static var entityName: String {get} 
.... 
    } 

extension Managed where Self: NSManagedObject { 
public static var entityName: String { return entity().name! } 
} 

然后我试图从协议扩展中检索entityName时崩溃了,我试着尝试荷兰国际集团插入对象...

enter image description here

它给我的错误“致命错误:意外发现零而展开的可选值”

我没有生成我NSManagedObjectSublcasses,我创造了他们我自己,但我相信我做得对。我有一种感觉,即在应用程序运行时,Core Data不会为“练习”选取我的Model类。这就是为什么实体名称没有任何返回。因此,这里是我的代码为我的模型类:

import UIKit 
import CoreData 

public class Exercise: NSManagedObject { 

@NSManaged public fileprivate(set) var category: Int16 
@NSManaged public fileprivate(set) var image1Path: String? 
@NSManaged public fileprivate(set) var image2Path: String? 
@NSManaged public fileprivate(set) var equipment: String? 
@NSManaged public fileprivate(set) var info: String? 
@NSManaged public fileprivate(set) var skill: String? 
@NSManaged public fileprivate(set) var primaryMuscle: String? 
@NSManaged public fileprivate(set) var otherMuscles: String? 

public static let normalizedNameKey = "name_normalized" 

@NSManaged fileprivate var primitiveName: String 

public var name: String { 
    set { 
     willChangeValue(forKey: #keyPath(Exercise.name)) 
     primitiveName = newValue 
     updateNormalizedName(newValue) 
     didChangeValue(forKey: #keyPath(Exercise.name)) 
    } 
    get { 
     willAccessValue(forKey: #keyPath(Exercise.name)) 
     let value = primitiveName 
     didAccessValue(forKey: #keyPath(Exercise.name)) 
     return value 
    } 
} 

fileprivate func updateNormalizedName(_ name: String) { 
    setValue(name.normalizedForSearch, forKey: Exercise.normalizedNameKey) 
} 

public var exerciseImage1: UIImage? { 
    guard let image = image1Path else {return nil} 
    return UIImage(named: image) 
} 

public var exerciseImage2: UIImage? { 
    guard let image = image2Path else {return nil} 
    return UIImage(named: image) 
} 

public static func insert(into context: NSManagedObjectContext, name: String, category: Int16, equipment: String?, skill: String?, primaryMuscle: String?, otherMuscles: String?, info: String?, image1: String?, image2: String?) -> Exercise { 
    let exercise: Exercise = context.insertObject() 
    exercise.name = name 
    exercise.category = category 
    exercise.info = info 
    exercise.primaryMuscle = primaryMuscle 
    exercise.otherMuscles = otherMuscles 
    exercise.equipment = equipment 
    exercise.skill = skill 

    if image1 != nil { 
     exercise.image1Path = image1 
    } 

    if image2 != nil { 
     exercise.image2Path = image2 
    } 

    return exercise 
} 

} 

    extension Exercise: Managed { 

    public static var defaultSortDescriptors: [NSSortDescriptor] { 
    return [NSSortDescriptor(key: #keyPath(name), ascending: false)] 
    } 

public static func defaultPredicate(muscleCategory: Int) -> NSPredicate 
{ 
    return NSPredicate(format: "%K == %ld", 
#keyPath(Exercise.category), muscleCategory) 
} 
} 

而这里的数据模型编辑器中的实体: enter image description here

任何想法可能是想错了?谢谢

+0

同样的问题,在实体()中坠毁。 – hstdt

+0

@hstdt:删除并重新创建。这解决了我的问题。 – Kobe

回答

1

我有相同的问题,使用完全相同的代码(核心数据书弗洛里安库格勒)。

我添加新实体+关系后创建新实体时出现我的问题,实体名称为零。
我通过删除实体并重新创建它来修复它。错误消失了。

0

Moin,

首先展开可选值。

public static var entityName: String 
    { 
     if let _returnName = entity().name{ 
      return _returnName 
     }else 
     { 
      return nil 
     } 
    } 
} 

Optional Chaining

CoreData:

练习

当你改变了你的DbModel之后,执行 “创建NSManagedObject子。” 所有功能集成到演习将覆盖。

使用一个单独的类象类ExerciseExtension

import UIKit 
import CoreData 

extension Exercise { 
    func setName(name : String) 
    { 
    self.name = name 
    } 
    ..... 
} 
+0

感谢您的回复。但我不让xCode为我自动生成子类,我自己写它们,所以我完全可以控制发生了什么。问题是,我写的类和数据模型之间可能存在缺失的链接。 –

+0

@LukeSmith你是如何解决这个问题的? – Alessandro

1

也许这是不是一个好主意,但它能够避免崩溃,现在...等待更好的解决方案。

SWIFT 4:

extension NSObject { 
    var className: String { 
     return String(describing: type(of: self)) 
    } 

    class var className: String { 
     return String(describing: self) 
    } 
} 

然后

static var entityName: String { 
    return self.className //insead of `entity().name!` 
}