HowTo debug Spinning Cursor in SwiftUI

Hi!

I have an app which works well but sometimes I get an endless spinning cursor but no logs. Any idea how to debug this?
Here is a sample stack:

Thread 1 Queue : com.apple.main-thread (serial)
#0 0x00000001aad8fc24 in AG::Graph::UpdateStack::update() ()
#1 0x00000001aad90494 in AG::Graph::update_attribute(AG::data::ptrAG::Node, unsigned int) ()
#2 0x00000001aad9e5d8 in AG::Subgraph::update(unsigned int) ()
#3 0x00000001aa96c55c in ___lldb_unnamed_symbol223674 ()
#4 0x00000001aa96d9e4 in ___lldb_unnamed_symbol223733 ()
#5 0x00000001a9b4b298 in ___lldb_unnamed_symbol122973 ()
#6 0x00000001aa68f224 in ___lldb_unnamed_symbol204729 ()
#7 0x00000001aa68dd48 in ___lldb_unnamed_symbol204648 ()
#8 0x00000001a9b4b258 in ___lldb_unnamed_symbol122972 ()
#9 0x00000001aa96d9ac in ___lldb_unnamed_symbol223732 ()
#10 0x00000001aa96d898 in ___lldb_unnamed_symbol223731 ()
#11 0x00000001aa061754 in ___lldb_unnamed_symbol161209 ()
#12 0x00000001aa750ed0 in ___lldb_unnamed_symbol210179 ()
#13 0x00000001aa753e18 in ___lldb_unnamed_symbol210286 ()
#14 0x00000001aa753e70 in ___lldb_unnamed_symbol210287 ()
#15 0x000000018126d9f0 in CFRUNLOOP_IS_CALLING_OUT_TO_AN_OBSERVER_CALLBACK_FUNCTION ()
#16 0x000000018126d8dc in __CFRunLoopDoObservers ()
#17 0x000000018126c514 in CFRunLoopRunSpecific ()
#18 0x000000018aabedf0 in RunCurrentEventLoopInMode ()
#19 0x000000018aabea80 in ReceiveNextEventCommon ()
#20 0x000000018aabe984 in _BlockUntilNextEventMatchingListInModeWithFilter ()
#21 0x000000018449397c in _DPSNextEvent ()
#22 0x0000000184492b18 in -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:] ()
#23 0x0000000184486f7c in -[NSApplication run] ()
#24 0x000000018445e3cc in NSApplicationMain ()
#25 0x00000001a95835ec in ___lldb_unnamed_symbol82618 ()
#26 0x00000001aa6e855c in ___lldb_unnamed_symbol207684 ()
#27 0x00000001a9f65e8c in static App.main() ()
#28 0x00000001026b42cc in static StundenplanApp.$main() at /…/StundenplanApp.swift:106
#29 0x00000001026b4bfc in main ()
#30 0x0000000180e37f28 in start ()

Xcode 14.3 on macOS 13.5

A profiler run shows that there is somehow an event flood:

153.08 Gc  100.0%	-	 	Stundenplan (24562)
152.92 Gc   99.8%	-	 	 start
152.91 Gc   99.8%	-	 	  static StundenplanApp.$main()
152.91 Gc   99.8%	-	 	   0x1a9f65e0c
152.91 Gc   99.8%	-	 	    0x1aa6e84b8
152.91 Gc   99.8%	-	 	     0x1a9583558
152.90 Gc   99.8%	-	 	      NSApplicationMain
152.90 Gc   99.8%	-	 	       -[NSApplication run]
152.43 Gc   99.5%	-	 	        -[NSApplication(NSEvent) _nextEventMatchingEventMask:untilDate:inMode:dequeue:]
433.97 Mc    0.2%	-	 	        -[NSApplication _handleEvent:]

and the main thread takes a CPU core for 100%.

Meanwhile I found the reason of the spinning cursor.
I implemented a context menu with the need to report the menu selection back to the app data.
For this I used .onReceive

.onReceive([self.selection].publisher.first()) { (value) in
	appData.objectWillChange.send()
	record.room = value
	appData.setDataChanged()
}

On Stackoverflow I found a clue that this would lead to a spinning cursor. Now I replaced it with .onChange

.onChange(of: selection) { _ in
   appData.objectWillChange.send()
   record.room = selection
   appData.setDataChanged()
}

and I get no longer a spinning cursor.
Perhaps this clue is helpful for other SwiftUI users.

Some tips for this issue:

  1. If there any AG cycle info showed in Xcode console, you can try adding AG_PRINT_CYCLES=2 and AG_TRAP_CYCLES=1 in the schema's environment variables to see more log info.
  2. If you can reproduce this issue on iOS 16- (From iOS 16+'s SwiftUI hide its symbol to ___lldb_unnamed_symbol), your sample stack will contain the related SwiftUI symbol. So that we can help dig this issue more easily.
  3. If you can give a minimal reproductive package/xcodeproj as attashment, maybe people can more easily help resolve this issue.
1 Like