2017-06-16 90 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!` 
}