The UI runs on the main thread, and so does your AppleScript code. You need either to break your handlers up, so that the UI has a chance to refresh, or force an update. One way is to regularly call a handler like this:
on fordEvent()
set theApp to current application's NSApp
set theMode to current application's NSEventTrackingRunLoopMode
set theMask to current application's NSDecimalNumber's decimalNumberWithString:"18446744073709551615"
repeat
set theEvent to (theApp's nextEventMatchingMask:theMask untilDate:(missing value) inMode:theMode dequeue:true)
if theEvent is missing value then exit repeat
theApp's sendEvent:theEvent
end repeat
end fordEvent
You need to have a rough understanding of how the event loop works. In simple terms, there is a queue of waiting events, that gets added to every time you click a button, move the mouse, hit a key, and so on. The run loop grabs the oldest in the queue, deals with it, updates the screen accordingly, then moves to the next. if the queue overflows, you get the spinning cursor.
So if you are performing a long-running task, if the user does something as simple as move the mouse, you might get a spinning cursor. In the past, you could at least force the screen to update using one of the display calls, which is what I suspect ASS did, but even that no longer works.
So you either have to break processes into multiple processes, cascading them via performSelector:withObject:afterDelay:, or periodically call a handler like the above, which will interrupt what’s happening to fetch the next waiting event manually.
It can be a challenge at times, and it’s a much bigger challenge for AppleScript because you can use background threads. ASOBjC is fine for putting an interface on a process, but it’s less than idea for trying to build full-blown apps.