I'm seeing these errors in the console when calling ModelContainer(for:migrationPlan:configurations) for iOS 18:
error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again.
CoreData: error: Attempting to retrieve an NSManagedObjectModel version checksum while the model is still editable. This may result in an unstable verison checksum. Add model to NSPersistentStoreCoordinator and try again.
Is this anything to be concerned about?
(Side note: "version" is misspelled in "verison checksum")
Post
Replies
Boosts
Views
Activity
Hello,
We haven't been getting crash logs for internal TestFlight builds.
I've tried intentionally causing a crash by calling fatalError() directly. The TestFlight feedback dialog appears and crash logs appear on the iPhone device itself, but they never appear in App Store Connect or Xcode Organizer.
The builds are all created by an Xcode cloud workflow and the Share analytics with App Developers setting is on.
I filed a radar ticket at FB15453505, but I wonder if others might have run into the same thing.
Has anyone else had this issue and figured out how to resolve it?
I'm running into an odd case where a model's reverse relationship is sometimes not set despite the forward relationship being there.
If the app is closed and reopened however, the reverse relationship for previously added data works.
For example, given three models Shelf, Item and ItemDetails:
@Model final class Shelf {
@Relationship(deleteRule: .cascade, inverse: \Item.primaryShelf)
var items: [Item] = []
init() {}
}
@Model final class Item {
var primaryShelf: Shelf?
var timestamp: Date
@Relationship(deleteRule: .cascade, inverse: \ItemDetail.item)
public var detail: ItemDetail?
init(primaryShelf: Shelf) {
self.primaryShelf = primaryShelf
self.timestamp = .now
}
}
@Model final class ItemDetail {
var item: Item?
init(item: Item) { self.item = item }
}
Now I want to simply create a shelf, some items and some itemdetails.
@Test func testRelationshipsThroughInit() async throws {
let schema = Schema([Shelf.self, Item.self, ItemDetail.self])
let config = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
let container = try ModelContainer(for: schema, configurations: [config])
let modelContext = ModelContext(container)
let shelf = Shelf()
modelContext.insert(shelf)
for _ in 0..<10 {
let item = Item(primaryShelf: shelf)
modelContext.insert(item)
let itemDetail = ItemDetail(item: item)
modelContext.insert(itemDetail)
}
try modelContext.save()
let fetchDescriptor = FetchDescriptor<Shelf>()
let shelves = try modelContext.fetch(fetchDescriptor)
// fails with a random number between 0 and 9 typically
#expect(shelves.first?.items.count == 10)
}
There seem to be two ways that this problem goes away. The first is changing the order of properties set in ItemDetail.init() so that the relationship is set after everything else:
@Model final class Item {
// ...
init(primaryShelf: Shelf) {
self.timestamp = .now
self.primaryShelf = primaryShelf
}
With this, everything seems to work fine. The other way seems to be manually setting the reverse relationship. So the loop above gets changed to:
for _ in 0..<10 {
let item = Item(primaryShelf: shelf)
modelContext.insert(item)
let itemDetail = ItemDetail(item: item)
modelContext.insert(itemDetail)
// add reverse relationship even though forward was set
shelf.items.append(item)
}
My question is, is this the expected behavior and If so, is there any place this is documented?
I've run into a problem related to navigation links in child Views containing a SwiftData @Query and a predicate.
When tapping on a NavigationLinks, the containing View is invalidated pausing the UI. When tapping back, the View is invalidated a second time during which time the View ignores any new taps for navigation leading to a poor user experience.
A complete example:
import SwiftUI
import SwiftData
@Model
final class Item {
var num: Int
init(num: Int) {
self.num = num
}
}
@main
struct TestSwiftDataApp: App {
var sharedModelContainer: ModelContainer = {
let schema = Schema([Item.self])
let modelConfiguration = ModelConfiguration(schema: schema, isStoredInMemoryOnly: true)
let container: ModelContainer
do {
container = try ModelContainer(for: schema, configurations: [modelConfiguration])
} catch {
fatalError("Could not create ModelContainer: \(error)")
}
// Add some sample data
Task { @MainActor in
for i in 0...1000 {
container.mainContext.insert(Item(num: i))
}
}
return container
}()
var body: some Scene {
WindowGroup {
ContentView()
}
.modelContainer(sharedModelContainer)
}
}
extension Color {
static func random() -> Color {
Color(red: .random(in: 0...1), green: .random(in: 0...1), blue: .random(in: 0...1))
}
}
struct ContentView: View {
var body: some View {
NavigationStack {
SubView()
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
struct SubView: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
}
}
The background colors of cells will shift every invalidation. In addition there's some debugging in there to show what's happening. When running it, I get
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @self changed.
SubView: @dependencies changed.
Then I tap on an item and it invalidates:
SubView: @self changed.
Tapping back invalidates it again during which time the UI ignores new taps:
SubView: @self changed.
The odd thing is, this behavior doesn't happen if the NavigationStack is moved to the child View with the NavigationLinks like this:
struct ContentView2: View {
var body: some View {
SubView2()
}
}
struct SubView2: View {
@Environment(\.modelContext) private var modelContext
@Query(filter: #Predicate<Item> { item in
item.num < 20
}, sort: \.num) private var items: [Item]
var body: some View {
let _ = Self._printChanges()
NavigationStack {
List {
ForEach(items) { item in
NavigationLink(value: item) {
Text("Item \(item.num)")
}.background(Color.random())
}
}
.navigationDestination(for: Item.self) { item in
Text("Item at \(item.num)")
}
}
}
}
When running this, there's one less change as well and no invalidations on tap or back:
SubView: @self, @identity, _modelContext, @128, @144 changed.
SubView: @dependencies changed.
The problem also doesn't happen if the @Query does not have a filter #Predicate.
Unfortunately, the application in question has a deeper hierarchy where views with a @Query with a predicate can navigation to other views with a @Query and predicate, so neither solution seems ideal.
Is there some other way to stop the invalidations from happening?