調査
removeFromEntity()とdelete()の違い
なんがねぇがと調べていたが、Album+CoreDataProperties.swiftファイル(エンティティを作ったら自動生成される)に
@objc(removeTracksObject:)
@NSManaged public func removeFromTracks(_ value: Track)
というメソッドが登録されていた。remove?じゃあ以下のようなdelete()
との違いは?今までCoreDataからデータを削除するのに使っていたのだが……
参考:
CoreDataをTableViewで扱う(リストの並び替え、削除との連携について)(Xcode12.4、Swift 5.3.2)(April 22, 2021)
static func delete(track: Track) {
guard let appDelegate = UIApplication.shared.delegate as? AppDelegate else {
abort()
}
let managedContext = appDelegate.persistentContainer.viewContext
managedContext.delete(track) // delete()を呼んだ後もsaveContext()されるまでは確定されない
}
swift - CoreData removeFrom vs delete - Stack Overflowにあるように
removeFromEntity()
はリレーションのみ削除delete()
はデータ自体を削除
実装の雰囲気
したがって、1つのalbum: Album
に対してリレーションをもっているtracks: [Track]
に対して、tracks[i]
のリレーションを変更する場合、移動先のアルバムをtargetAlbum: Album
として
album.removeFromTracks(tracks[i]) // 現在のAlbumとrelationshipを削除
tracks[i].index = Int16(targetAlbum.count) // (CoreData上は並び順が保存されないのでAttributeとしてindexを加えている場合、`tracks[i].index`を変更する。この場合は移動先末尾に加えられることになる。)
targetAlbum.addToTracks(tracks[i]) // 移動先のAlbumに加える
tracks.remove(at: i) // albumもちのtracksからは削除
// 移動したtracks[i]より後ろの要素分のみ、CoreDataのindexを更新する
let filteredTracks = tracks.lazy.filter({ $0.index > Int16(i) })
for (index, filteredTracks) in zip(filteredTracks.indices, filteredTracks) { // filteredTracks.enumerated()ではindexが必ず0から始まってしまうのでzip()を使う
filteredTracks.index = Int16(index)
}
細かくコメントを書いたのでとくに解説はなし。
まとめ
ググルの適当だったからか、直接リレーションを操作しているような記事には行き着かなかった。なので自分の思いつき。まあ無難な実装ではないか?