2017-09-12 16 views
0

我正在進行「中等重量」核心數據遷移。我正在使用映射模型從一個傳統商店/數據模型遷移到不同的商店和不同的模型(即完全不同的.xcdatamodeld)文件,並在適用的情況下使用自定義的NSEntityMigrationPolicy對象。核心數據遷移:無法將類型'NSManagedObject_MyType'的值轉換爲'MyModule.MyType'

以前我有各種與對象圖無關的對象,現在我想擁有一個主對象Library,使我能夠輕鬆地清除所有關聯的數據(使用級聯刪除規則)。

我在遷移過程中,因爲一個自定義的方法在我的NSEntityMigrationPolicy子類中遇到的問題:

class LegacyToModernPolicy: NSEntityMigrationPolicy { 

func libraryForManager(_ manager: NSMigrationManager) -> Library { 

    let fetchRequest: NSFetchRequest<Library> = NSFetchRequest(entityName: Library.entity().name!) 

    fetchRequest.predicate = nil 
    fetchRequest.sortDescriptors = [NSSortDescriptor(key: "filename", ascending: true)] 
    fetchRequest.fetchLimit = 1 

    do { 
     // will fail here if NSFetchRequest<Library> 
     let results = try manager.destinationContext.fetch(fetchRequest) 
     log.info("results: \(results)") 

     if results.count == 1 { 
      // can fail here if NSFetchRequest<NSManagedObject> 
      return results.first! as! Library 
     } else { 
      let newLib = Library(context: manager.destinationContext) 
      return newLib 
     } 

    } catch { 
     log.error("Error fetching: \(error.localizedDescription)") 
    } 

    let newLib = Library(context: manager.destinationContext) 
    return newLib 
    } 
} 

一個會拋出異常,並且錯誤信息是:

Could not cast value of type 'NSManagedObject_Library_' (0x6100000504d0) to 'SongbookSimple.Library' (0x101679180).

問題是,爲什麼會發生這種情況,這有什麼關係?因爲正在發生遷移,所以或許足以使用正確的實體描述返回NSManagedObject

+0

我只是跳到這裏來報告我的發現,以便別人不必花費時間。值得注意的摘錄來自「The Migration Process」(你可以谷歌並把你帶到蘋果網站......我不會發布鏈接,因爲蘋果鏈接定期死亡:) 「遷移過程本身分三個階段。使用禁用驗證規則的源和目標模型的副本,並將所有實體的類更改爲NSManagedObject。「 所以是的,在這些策略中,你應該返回NSManagedObject而不是你的子類。 – horseshoe7

回答

0

原因是在遷移期間,您不應該使用NSManagedObject子類的實例。你需要以NSManagedObject的形式表達所有這些。所以,上面的代碼必須成爲:

class LegacyToModernPolicy: NSEntityMigrationPolicy { 

static func find(entityName: String, 
       in context: NSManagedObjectContext, 
       sortDescriptors: [NSSortDescriptor], 
       with predicate: NSPredicate? = nil, 
       limit: Int? = nil) throws -> [NSManagedObject] { 

    let fetchRequest: NSFetchRequest<NSManagedObject> = NSFetchRequest(entityName: entityName) 
    fetchRequest.predicate = predicate 
    fetchRequest.sortDescriptors = sortDescriptors 
    if let limit = limit { 
     fetchRequest.fetchLimit = limit 
    } 

    do { 
     let results = try context.fetch(fetchRequest) 
     return results 
    } catch { 
     log.error("Error fetching: \(error.localizedDescription)") 
     throw error 
    } 
} 

func libraryForManager(_ manager: NSMigrationManager) -> NSManagedObject { 

    do { 
     var library: NSManagedObject? = try LegacyToModernPolicy.find(entityName: Library.entity().name!, 
               in: manager.destinationContext, 
               sortDescriptors: [NSSortDescriptor(key: "filename", ascending: true)], 
               with: nil, 
               limit: 1).first 
     if library == nil { 
      let dInstance = NSEntityDescription.insertNewObject(forEntityName: Library.entity().name!, into: manager.destinationContext) 

      // awakeFromInsert is not called, so I have to do the things I did there, here: 
      dInstance.setValue(Library.libraryFilename, forKey: #keyPath(Library.filename)) 
      dInstance.setValue(NSDate(timeIntervalSince1970: 0), forKey: #keyPath(Library.updatedAt)) 
      library = dInstance 
     } 

     return library! 

    } catch { 
     fatalError("Not sure why this is failing!") 
    } 
}} 

您可以詳細瞭解如何與核心數據遷移here我不那麼有趣的經歷。

相關問題