Running an app and the beachball

(Andreas Kiel) #1

Something I haven’t taken care of was that running a compiled app always shows the beach ball and the UI is unresponsive.

Was happy enough to get things transported from the really old ASS Xcode 3.2 app to current ASObjC.

So when the app processes some file there is no way to stop the process. That never had been a problem before.

Any hint where to start searching?

(Shane Stanley) #2

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"
			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

(Andreas Kiel) #3

Thanks Shane.

Sorry for the late reply.

My English is not that good, but maybe you understand “I can hear your words, but don’t really understand”

I’ve succeeded to create something similar (with the help of your book) which seems to work, but I’m not happy with it.

(Shane Stanley) #4

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.