如何在执行核心数据迁移时获取关系实体?
How to fetch relationship entities when performing a core data migration?
我正在执行核心数据迁移。我的迁移有这个子类:
class TagtoSkillMigrationPolicyV1toV2: NSEntityMigrationPolicy {
override func createDestinationInstances( forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
// 1 - create destination instance of skill and skillmetadata
let skillEntityDescription = NSEntityDescription.entity( forEntityName: "Skill",in: manager.destinationContext)
let newSkill = Skill(entity: skillEntityDescription!, insertInto: manager.destinationContext)
let skillMetaDataDescription = NSEntityDescription.entity(forEntityName: "SkillMetaData", in: manager.destinationContext)
newSkill.metaData = SkillMetaData(entity: skillMetaDataDescription!, insertInto: manager.destinationContext)
var posts = sInstance.value(forKey: "posts")
posts.sort {
([=10=].timeStamp! as Date) < (.timeStamp! as Date)
}
if let mostRecentThumbnail = posts.first?.postImage {
let thumbnail = Utils.makeThusmbnail(url: URL(string: mostRecentThumbnail)!, for: 150.0)
newSkill.metaData?.thumbnail = thumbnail?.pngData()
}
if let name = sInstance.value(forKey: "name"){
newSkill.setValue(name, forKey: "name")
}
manager.associate(sourceInstance: sInstance, withDestinationInstance: newSkill, for: mapping)
}
}
此自定义迁移是从我的旧标签实体到我的新技能实体。对于每个标签,它创建一个技能实体和一个附加到它的技能元数据实体。 .xcmappingmodel 文件中没有任何条目,因为我正在手动执行所有操作 - 如果我仍然需要在那里输入,请告诉我。
现在,当它运行时,它会发出信号 SIGABRT:
Could not cast value of type '_NSFaultingMutableOrderedSet' (0x7fff87c44e80) to 'NSArray' (0x7fff87c51fb0).
2020-04-14 15:55:40.108927-0700 SweatNetOffline[28046:3645007] Could not cast value of type '_NSFaultingMutableOrderedSet' (0x7fff87c44e80) to 'NSArray' (0x7fff87c51fb0).
当我设置断点并检查 sInstance.value(forKey: "posts")
时,我得到
▿ Optional<Any>
- some : Relationship 'posts' fault on managed object (0x6000010dcf00) <NSManagedObject: 0x6000010dcf00> (entity: Tag; id: 0xdf4b05c2e82b2c4e <x-coredata://A6586C18-60C3-40E7-B469-293A50EB5728/Tag/p1>; data: {
latestUpdate = "2011-03-13 00:17:25 +0000";
name = flowers;
posts = "<relationship fault: 0x600002607f40 'posts'>";
uuid = "4509C1B3-7D0F-4BBD-AA0B-7C7BC848DA80";
})
所以它并没有完全加载这些帖子 - 它在那里给出了那个错误。
目标是从最新的帖子中获取缩略图。我怎样才能访问这个关系项目?
我找到了一种使用
的方法
let lastThumbnail = sInstance.mutableOrderedSetValue(forKeyPath: "posts.postImage").lastObject
阅读this帮助很大。我的理解是在迁移的这一点上,我们正在处理 NSManagedObjects 而不是实际的模型,它通常在核心数据中具有 "posts" 之类的属性。
在Objective-C中,尤其是在swift中,在某种程度上,NSObjects是通过键值编码访问的。它们是间接访问的——这意味着你不是在读取对象本身,而是在读取 NSMutableOrderedSet 想要为你显示的那个键——所以它可以在呈现它之前对它做一些事情。因此,例如,您不能仅获取 "forKey: posts" 然后期望 post 具有您的 post 通常具有的属性。如果任何人知道更多,欢迎充实这个解释:)。
我试图做的一件事是以可排序的方式通过该键路径获取 - 这样我就可以找到具有最新时间戳的 post,然后使用相关的缩略图。相反,我使用的是 .lastObject ,因为这是一个 NSMutableOrderedSet 而不是 NSMutableSet,因为我的原始模型将此关系指定为有序关系。这意味着它会选择最后插入的项目,现在对我来说没问题。如果有人有建议,仍然对过滤该结果的方法感兴趣。
我正在执行核心数据迁移。我的迁移有这个子类:
class TagtoSkillMigrationPolicyV1toV2: NSEntityMigrationPolicy {
override func createDestinationInstances( forSource sInstance: NSManagedObject, in mapping: NSEntityMapping, manager: NSMigrationManager) throws {
// 1 - create destination instance of skill and skillmetadata
let skillEntityDescription = NSEntityDescription.entity( forEntityName: "Skill",in: manager.destinationContext)
let newSkill = Skill(entity: skillEntityDescription!, insertInto: manager.destinationContext)
let skillMetaDataDescription = NSEntityDescription.entity(forEntityName: "SkillMetaData", in: manager.destinationContext)
newSkill.metaData = SkillMetaData(entity: skillMetaDataDescription!, insertInto: manager.destinationContext)
var posts = sInstance.value(forKey: "posts")
posts.sort {
([=10=].timeStamp! as Date) < (.timeStamp! as Date)
}
if let mostRecentThumbnail = posts.first?.postImage {
let thumbnail = Utils.makeThusmbnail(url: URL(string: mostRecentThumbnail)!, for: 150.0)
newSkill.metaData?.thumbnail = thumbnail?.pngData()
}
if let name = sInstance.value(forKey: "name"){
newSkill.setValue(name, forKey: "name")
}
manager.associate(sourceInstance: sInstance, withDestinationInstance: newSkill, for: mapping)
}
}
此自定义迁移是从我的旧标签实体到我的新技能实体。对于每个标签,它创建一个技能实体和一个附加到它的技能元数据实体。 .xcmappingmodel 文件中没有任何条目,因为我正在手动执行所有操作 - 如果我仍然需要在那里输入,请告诉我。
现在,当它运行时,它会发出信号 SIGABRT:
Could not cast value of type '_NSFaultingMutableOrderedSet' (0x7fff87c44e80) to 'NSArray' (0x7fff87c51fb0).
2020-04-14 15:55:40.108927-0700 SweatNetOffline[28046:3645007] Could not cast value of type '_NSFaultingMutableOrderedSet' (0x7fff87c44e80) to 'NSArray' (0x7fff87c51fb0).
当我设置断点并检查 sInstance.value(forKey: "posts")
时,我得到
▿ Optional<Any>
- some : Relationship 'posts' fault on managed object (0x6000010dcf00) <NSManagedObject: 0x6000010dcf00> (entity: Tag; id: 0xdf4b05c2e82b2c4e <x-coredata://A6586C18-60C3-40E7-B469-293A50EB5728/Tag/p1>; data: {
latestUpdate = "2011-03-13 00:17:25 +0000";
name = flowers;
posts = "<relationship fault: 0x600002607f40 'posts'>";
uuid = "4509C1B3-7D0F-4BBD-AA0B-7C7BC848DA80";
})
所以它并没有完全加载这些帖子 - 它在那里给出了那个错误。
目标是从最新的帖子中获取缩略图。我怎样才能访问这个关系项目?
我找到了一种使用
的方法let lastThumbnail = sInstance.mutableOrderedSetValue(forKeyPath: "posts.postImage").lastObject
阅读this帮助很大。我的理解是在迁移的这一点上,我们正在处理 NSManagedObjects 而不是实际的模型,它通常在核心数据中具有 "posts" 之类的属性。
在Objective-C中,尤其是在swift中,在某种程度上,NSObjects是通过键值编码访问的。它们是间接访问的——这意味着你不是在读取对象本身,而是在读取 NSMutableOrderedSet 想要为你显示的那个键——所以它可以在呈现它之前对它做一些事情。因此,例如,您不能仅获取 "forKey: posts" 然后期望 post 具有您的 post 通常具有的属性。如果任何人知道更多,欢迎充实这个解释:)。
我试图做的一件事是以可排序的方式通过该键路径获取 - 这样我就可以找到具有最新时间戳的 post,然后使用相关的缩略图。相反,我使用的是 .lastObject ,因为这是一个 NSMutableOrderedSet 而不是 NSMutableSet,因为我的原始模型将此关系指定为有序关系。这意味着它会选择最后插入的项目,现在对我来说没问题。如果有人有建议,仍然对过滤该结果的方法感兴趣。