SwiftUI, ModelContext throwing layout engine exception

A class which holds a list of spells.


@MainActor
class ListOfSpells : ObservableObject {
	@Published var allSpells : [String] = []
	
	@Published var currSpell : SpellInfo
	
	@Published var spell : String = "" {
		didSet {
			Task {
				if let spl = await DBAccess.instance.GetSpellInfo(spell: self.spell) {
					currSpell = SpellInfo(info: spl)
				}
				else {
					currSpell = SpellInfo(info: dummySpellField)
				}
			}
			
		}
	}
	
	@Published var filterString = ""
	
	init() {
		currSpell = SpellInfo(info: dummySpellField)
		
		Task {
			do {
				allSpells = try await DBAccess.instance.GetAllNames(force: false)
			}
			catch let E {
				print(E.localizedDescription)
			}
		}
	}
}

SwiftUI file

@Model
final class ThemeSpell {
	var spell : String
	
	init(spell S: String) {
		spell = S
	}
}

struct ContentView: View {
    @Environment(\.modelContext) private var modelContext
	@StateObject var spells = ListOfSpells()
	@Query private var themeSpells : [ThemeSpell]

    var body: some View {
		HStack {
			List(selection: $spells.spell) {     **
			//List {                             **
				ForEach(spells.allSpells, id: \.self) { spell in
					Text(spell)
				}
			}.frame(width: 240)
				
			
			Spacer()
			
			VStack {
				//SpellUIView(spell: spells)
				
				HStack {
					Button(">>>") {
						addItem(name: spells.spell)
					}
					.frame(width: 80)
					.keyboardShortcut(.space, modifiers: [.option])
				}
				
			}
			.frame(height: 600)
			
			Spacer()
			
			List {
				ForEach(themeSpells) { item in
					Text(item.spell)  ***
				}
			}.frame(width: 240)
			
		}
    }

	private func addItem(name: String) {
		let newItem = ThemeSpell(spell: name)
		modelContext.insert(newItem)
    }
}

** commenting out selection:$spells.spell makes no difference.

*** if this is left in, the app crashes with the following exception:

Terminating app due to uncaught exception 'NSInternalInconsistencyException', reason: 'Modifications to the layout engine must not be performed from a background thread after it has been accessed from the main thread.'

Can't post entire stack trace. Too big. But the exception is raised a background thread.

	0   CoreFoundation                      0x000000018dd0c8c0 __exceptionPreprocess + 176
	1   libobjc.A.dylib                     0x000000018d805eb4 objc_exception_throw + 60
	2   CoreAutoLayout                      0x000000019640e240 -[NSISEngine tryToOptimizeReturningMutuallyExclusiveConstraints] + 0
	3   CoreAutoLayout                      0x000000019640e63c -[NSISEngine withBehaviors:performModifications:] + 36
	4   AppKit                              0x0000000192193fac -[NSView(NSConstraintBasedLayoutInternal) _withAutomaticEngineOptimizationDisabled:] + 48
	5   AppKit                              0x00000001921936a4 __60-[NSView(NSConstraintBasedLayoutInternal) _setLayoutEngine:]_block_invoke + 328
	6   AppKit                              0x0000000192193510 -[NSView(NSConstraintBasedLayoutInternal) _setLayoutEngine:] + 492
	7   AppKit                              0x00000001914cf998 make_and_host_engine + 144
	8   AppKit                              0x0000000192192cf4 -[NSView(NSConstraintBasedLayoutInternal) _didChangeHostsAutolayoutEngineTo:] + 56
	9   AppKit                              0x0000000192193ac8 -[NSView(NSConstraintBasedLayoutInternal) _tryToEncapsulateSubtreeLayout] + 100
	10  AppKit                              0x00000001914fae9c -[NSTableRowData _initializeRowView:atRow:] + 192
	11  AppKit                              0x00000001914f9b74 -[NSTableRowData _preparedRowViewForRow:storageHandler:] + 120
	12  AppKit                              0x000000019202d1bc __65-[NSTableRowData _doAutomaticRowHeightsForInsertedAndVisibleRows]_block_invoke_2 + 160
	13  Foundation                          0x000000018ed95704 __NSINDEXSET_IS_CALLING_OUT_TO_A_BLOCK__ + 24
	14  Foundation                          0x000000018f494fbc __NSIndexSetEnumerateBitfield + 348
	15  AppKit                              0x000000019202cf1c __65-[NSTableRowData _doAutomaticRowHeightsForInsertedAndVisibleRows]_block_invoke + 424
	16  AppKit                              0x000000019202d440 -[NSTableRowData _keepTopRowStableAtLeastOnce:andDoWorkUntilDone:] + 256
	17  AppKit                              0x00000001915082e8 -[NSTableRowData _updateVisibleViewsBasedOnUpdateItems] + 1300
	18  AppKit                              0x00000001914f0a6c -[NSTableRowData endUpdates] + 328
	19  AppKit                              0x00000001914f08e0 -[NSTableView _endUpdateWithTile:] + 108

My SwiftUI code is a modification of the standard code created with New Project. The standard code uses a toolbarItem '+' to create a new item. My code uses a list of strings to which can be added to the model.

Post not yet marked as solved Up vote post of tridiak Down vote post of tridiak
334 views

Replies

Figured out the issue. When the model data is saved to file and reloaded, any attempts to add more items will cause the crash indicated above. This is reproducible when creating a Document App project using SwiftUI/Swift/SwiftData options.

  • Has anyone gotten a SwiftData document app to work on macOS? (Meaning, being able to re-open a saved document and edit it.)

    I'm having the same issue here (this even happens with the built-in template for a Multiplatform Document app using SwiftData) -- has anyone found a workaround? I filed a DTS to see if they can provide a work-around. I'll update here if they are able to provide one.

  • Trying as well, same issue. No workaround. When opening a document the underlying managedobject context is created on another thread than when creating a a new document. Just found this post after adding my own.

Add a Comment