I further investigated this issue. The problem seems to be in the following line. Here I inject the viewContext into my view hierarchy.
ContentView()
.environment(\.managedObjectContext, persistence.container.viewContext)
First I deactivate the CloudKit Sync. The persistence container will be reinitialized. Therefore, I get a new instance of the viewContext.
021-12-04 22:08:19.063535+0100 TestApp[67682:1918331] [persistence] Deactivating Core Data CloudKit sync.
2021-12-04 22:08:19.063750+0100 TestApp[67682:1918331] [persistence] Persistence -> viewContext before deactivating cloudKit = <NSManagedObjectContext: 0x60000129d040>
2021-12-04 22:08:19.071889+0100 TestApp[67682:1918331] [persistence] Persistence set to local CoreData.
2021-12-04 22:08:19.102950+0100 TestApp[67682:1918331] [persistence] Persistence -> viewContext after deactivating cloudKit = <NSManagedObjectContext: 0x6000012f4ea0>
Afterwards I add a new test entity to the viewContext. The viewContext stored in the appDelegate has been set correctly. The @Environment(\.managedObjectContext) private var viewContext ones it not updated automatically.
Is there a way to force the update?
2021-12-04 22:08:47.352342+0100 TestApp[67682:1918331] [common] Adding test entitiy.
2021-12-04 22:08:47.352552+0100 TestApp[67682:1918331] [common] ShotResultList -> environment viewContext = <NSManagedObjectContext: 0x60000129d040>
2021-12-04 22:08:47.352699+0100 TestApp[67682:1918331] [common] ShotResultList -> appDelegate viewContext = <NSManagedObjectContext: 0x6000012f4ea0>
Post
Replies
Boosts
Views
Activity
I fixed the issue mentioned above by the following changes.
The persistence instance can be reloaded in order switch between NSPersistentCloudKitContainerand NSPersistentContainer. After every reload I increase the attribute persistenceContainerReloaded by one. The line .id(persistence.persistenceContainerReloaded)triggers the reload of the full view hierarchy. Now every view uses the correct viewContext instance.
@main
struct TargetShooterApp: App {
@StateObject var persistence: Persistence = Persistence.shared
var body: some Scene {
WindowGroup {
ContentView()
.environment(\.managedObjectContext, persistence.container.viewContext)
.id(persistence.persistenceContainerReloaded)
}
}
}
Now I faced a new issue. I still see CoreData+CloudKit debug outputs in the terminal, although the storeDescription.cloudKitContainerOptionsis nil.
The device is still able to sync local changes to other devices, but is not capable to receive changes made on other devices. After the restart of the app, everything works as expected. It seems, there is still a background process NSCloudKitMirroringDelegate running, uploading CoreData changes.
Any ideas?
I'm using Xcode 13.2.1 with Simulator iOS 15.2 and iPhone 12 Pro iOS 15.2. I'm still facing the same issue.
It's getting even worse.
I need to track when a view disappears. Sometime the onDisappear is called and sometimes not.
Hi,
I checked out some WWDC 2021 videos and found some hints. The following code changes the sort order of the groups. That's works fine so far. But in addition to that I'd like to change the sort order of the timestamps as well.
How can I do this?
As soon as I add a second sort descriptor, the app crashes with the previous error.
import SwiftUI
import CoreData
struct ContentView: View {
@Environment(\.managedObjectContext) private var viewContext
@State var counter: UInt32 = 0
@State var order: SortOrder = .reverse
@SectionedFetchRequest(
sectionIdentifier: \.group!,
sortDescriptors: [SortDescriptor(\Item.group, order: .reverse)],
predicate: nil,
animation: .linear
)
private var sectionedItems: SectionedFetchResults<String, Item>
var body: some View {
NavigationView {
List {
ForEach(sectionedItems) { section in
Section(header: Text("\(section.id)")) {
ForEach(section, id: \Item.id) { item in
NavigationLink {
VStack {
Text("Timestamp: \(item.timestamp!, formatter: itemFormatter)")
Text("UUID: \(item.uniqueId!)")
Text("\(item.group!)")
}
} label: {
VStack {
Text(item.timestamp!, formatter: itemFormatter)
}
}
}
}
}
}
.navigationTitle("Sectioned List")
.toolbar {
ToolbarItem(placement: .primaryAction) {
Button(action: addItem) {
Label("Add Item", systemImage: "plus")
}
}
ToolbarItem(placement: .principal) {
Button(action: toggleSortOrder) {
Label("Sort Order", systemImage: "arrow.up.arrow.down")
}
.onChange(of: order) { _ in
print("onChange order = \(order)")
let sortDescriptors = [SortDescriptor(\Item.group, order: order)]
let config = sectionedItems
config.sortDescriptors = sortDescriptors
config.sectionIdentifier = \Item.group!
}
}
}
}
}
private func addItem() {
// ...
}
private func toggleSortOrder() {
order = (order == .reverse ? .forward : .reverse)
print("toggleSortOrder: order = \(order)")
}
}
I implemented an example project which shows the same issue.
import SwiftUI
import Charts
struct Values: Identifiable {
var name: String
var value: Int
var id = UUID()
}
/// Displays an exemplary bar chart.
struct BarChartView: View {
var chartData: [Values] = [.init(name: "A", value: 93),
.init(name: "B", value: 92),
.init(name: "C", value: 90),
.init(name: "D", value: 91)]
var minValueYAxis: Int = 89
var maxValueYAxis: Int = 93
var average: Double {
get {
var sum = 0
for data in chartData {
sum += data.value
}
return Double(sum) / Double(chartData.count)
}
}
var body: some View {
GroupBox("Results") {
Chart {
ForEach(chartData) { values in
BarMark(x: .value("name", values.name), y: .value("value", values.value))
.cornerRadius(5.0)
.annotation(position: .overlay, alignment: .top, spacing: 10.0) {
Text("\(values.value)")
.foregroundColor(.white)
.fontWeight(.bold)
}
RuleMark(y: .value("average", average))
.foregroundStyle(.red)
.annotation(position: .overlay, alignment: .bottomTrailing, spacing: 0.0) {
Text("ø = \(String(format: "%.2f", average))")
.foregroundColor(.red)
}
}
}
.chartYScale(domain: minValueYAxis...maxValueYAxis)
.frame(height: 220, alignment: .top)
}
.backgroundStyle(Color.white)
.shadow(radius: 5.0, x: 2.0, y: 2.0)
.padding()
}
}
struct ContentView: View {
var body: some View {
ScrollView {
VStack {
Text("Chart 1")
BarChartView()
}
}
}
}
If I remove the line .chartYScale(domain: minValueYAxis...maxValueYAxis), everything looks ok, but it is hard to see the differences between the bars.
And here's the resulting views on the iPhone 13 simulator.
This seems not to be an iPhone 15 or 15 Pro Max. I experience same issues with other simulator devices.
Xcode 15 + 16.4 simulator has shows similar issues.
This seems not to be an iPhone 15. I experience same issues with other simulator devices.
Xcode 15 + iOS 16.4 simulator shows similar issues. It is extremely slow, and does not react on any tap gesture.
Not really. I found a way to unload and reload my persistence stores. But my App crashes because the old viewContext is still used in the view hierarchy.
Therefore, I tried to completely unload my root view (ContentVIew) by switching to another view. But the ContentView() won't be released from memory, even if it is not shown.
@StateObject private var appRootManager = AppRootManager()
var body: some Scene {
WindowGroup {
Group {
switch appRootManager.currentRoot {
case .splash:
SplashView()
case .reloading:
StatusView()
case .ready:
ContentView()
}
.environmentObject(appRootManager)
}
}
}
Not really. I found a way to unload and reload my persistence stores. But my App crashes because the old viewContext is still used in the view hierarchy.
Therefore, I tried to completely unload my root view (ContentVIew) by switching to another view. But the ContentView() won't be released from memory, even if it is not shown.
@StateObject private var appRootManager = AppRootManager()
var body: some Scene {
WindowGroup {
Group {
switch appRootManager.currentRoot {
case .splash:
SplashView()
case .reloading:
StatusView()
case .ready:
ContentView()
}
.environmentObject(appRootManager)
}
}
}