SwiftDataで1:多のモデルを定義した際のデータ複製について
解決したいこと
SwiftDataで1:多(one to many)の関係のモデルを定義しています。
画面ではリスト表示でGroupを表示して、リストをタップしたらGroupと紐づいているChartがリスト表示されます。
ディレクトリと内蔵ファイルのような関係です。
今回、Groupリストをスライドした際、そのGroupを複製する機能を実装しています。
しかし、下記のコードでその処理を実行するとアプリがクラッシュします。
クラッシュ箇所は@Relationship
のマクロ内のsetです。
この原因と解決法を教えていただきたいです。
下記のサイトでアプリの紹介をしているので、アプリをダウンロードいただけるとイメージが掴みやすいかもしれません。
発生している問題・エラー
import SwiftUI
import SwiftData
@Model
final class Group: Identifiable {
@Attribute(.unique) var id: UUID
var title: String
var category: [String]
@Relationship(deleteRule: .cascade, inverse: \Chart.group) var charts: [Chart]
// ↓ここから
{
@storageRestrictions(accesses: _$backingData, initializes: _charts)
init(initialValue) {
_$backingData.setValue(forKey: \.charts, to: initialValue)
_charts = _SwiftDataNoType()
}
get {
_$observationRegistrar.access(self, keyPath: \.charts)
return self.getValue(forKey: \.charts)
}
set {
_$observationRegistrar.withMutation(of: self, keyPath: \.charts) {
self.setValue(forKey: \.charts, to: newValue) // ここでクラッシュする(Thread 1: EXC_BREAKPOINT (code=1, subcode=0x1cb459e90))
}
}
}
// ↑ここまではマクロの内容
init(title: String, category: [String], charts: [Chart] = []) {
self.id = UUID()
self.title = title
self.category = category
self.charts = charts
}
func copy() -> Group {
let copyGroup = Group(title: self.title, category: self.category)
self.charts.forEach { originalChart in
let copiedChart = originalChart.copy(group: copyGroup)
copyGroup.charts.append(copiedChart)
}
return copyGroup
}
}
@Model
final class Chart: Identifiable {
var id: UUID
var group: Group?
var title: String
var data: [String : Double]
init(group: Group, title: String, data: [String : Double]) {
self.id = UUID()
self.group = group
self.title = title
self.data = data
}
func copy(group: Group) -> Chart {
return Chart(group: group, title: self.title, data: self.data)
}
}
複製機能の参考にしたサイト
試したこと
chartsの代入部分が問題なのかなと思い、Group.copyのcharts代入部分を何パターンか試しました。
let copiedCharts = self.charts.map { originalChart in
let copiedChart = originalChart.copy(group: copyGroup)
return copiedChart
}
copyGroup.charts = copiedCharts
copyGroup.charts = self.charts.map { $0.copy(group: copyGroup) }