Add Indeterminate Circular Progress Indicator to Xcode 10 ASOBJ-C Proj

I have a rather long AppleScript that I’ve converted to a AppleScript Obj-C app using Xcode 10. The only interface object is a push button that starts the script. It runs fine, but I’d like to add a Indeterminate Circular Progress Indicator to show that the script is processing – so users do not click the button any additional times until the script has completed with it’s current task. Ideally, it might be helpful if I disabled the push button while the Indeterminate Circular Progress Indicator is actively spinning. I’m new to Xcode, so my knowledge of Xcode is very limited. Binding the “Start” button to the delegate is the only thing I seem to get working. What additional steps would be needed to add a Determinate Bar Progress Indicator in Xcode?

I noted there are similar and outdated post. I’ve reviewed many of them, but still need guidance.

Example:

on startScript_(sender)

-- Additional task code would go here.
    
end startScript_

Mac OS 10.13.6
AppleScript Version 2.7
Xcode Version 10.1 (10B61)

You may not realise it, but what you’re asking for is effectively how to write an Xcode-based AppleScriptObjC app, and that’s not something easily answered in a single reply. To make it more complicated, there’s more than one way to do what you want.

here’s one approach. To start, add a progress indicator to your window, and make a property that is an outlet to it – one that has an initial value of missing value, and that you link by control-clicking on the progress indicator and choosing the property as a referencing outlet.

Your code should look something like this:


property progIndicator : missing value

on startScript:sender
	sender's setEnabled:false
	progIndicator's startAnimation:me
	my performSelector:"continueScript:" withObject:me afterDelay:0.1
end startScript:

on continueScript:sender
	-- do your stuff here
	sender's setEnabled:true
	progIndicator's stopAnimation:me
end continueScript:

That will get you started, although you may still see the spinning beach ball if your script takes a long time. You can find the solution to that, which is a bit more complicated, by searching here.

Good luck.

Thank you Shane, I really appreciate your reply.

I tried your suggestion and didn’t have any luck. I am not able to link MainMenu.xib’s progress indicator icon to the progIndicator property. I’ve included a couple screen shots below.

AppDelegate.applescript:

[code]use AppleScript version “2.4” – Yosemite (10.10) or later
use framework “Foundation”
use scripting additions

script AppDelegate
property parent : class “NSObject”

-- IBOutlets
property theWindow : missing value
property progIndicator : missing value

on startScript:sender
    sender's setEnabled:false
    progIndicator's startAnimation:me
    my performSelector:"continueScript:" withObject:me afterDelay:0.1
end startScript:

on continueScript:sender

     -- do your stuff here -- START
     -- EXAMPLE CODE:
     set My_List to {"1", "2", "3"} as list
     repeat with i in My_List
         display dialog i giving up after 1
     end repeat
     -- do your stuff here -- END

    sender's setEnabled:true
    progIndicator's stopAnimation:me
end continueScript:

on applicationWillFinishLaunching_(aNotification)
	-- Insert code here to initialize your application before any files are opened
end applicationWillFinishLaunching_

on applicationShouldTerminate_(sender)
	-- Insert code here to do any housekeeping before your application quits 
	return current application's NSTerminateNow
end applicationShouldTerminate_

end script[/code]

Also, I have 2 questions regarding your initial reply.

1.
Your syntax is a bit different than what I originally used. Are they equivalent? I tried both ways.

My Code: on startScript_(sender)
Your Code: on startScript:sender

2.
You said:
“…which is a bit more complicated, by searching here”. By “here”, did you mean in the AppleScriptObjC and Xcode forum? It almost sounded like you meant to include a URL link.

Button Linking

Progress Indicator

Error Message / Code

Sorry about the code flub.

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

script AppDelegate
	property parent : class "NSObject"
	
	-- IBOutlets
	property theWindow : missing value
	property progIndicator : missing value
	
	on startScript:sender
		sender's setEnabled:false
		progIndicator's startAnimation:me
		my performSelector:"continueScript:" withObject:me afterDelay:0.1
	end startScript:
	
	on continueScript:sender
		
		-- do your stuff here -- START
		-- EXAMPLE CODE:
		set My_List to {"1", "2", "3"} as list
		repeat with i in My_List
			display dialog i giving up after 1
		end repeat
		-- do your stuff here -- END
		
		sender's setEnabled:true
		progIndicator's stopAnimation:me
	end continueScript:
	
	on applicationWillFinishLaunching:aNotification
		-- Insert code here to initialize your application before any files are opened
	end applicationWillFinishLaunching:
	
	on applicationShouldTerminate:sender
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate:
	
end script

They don’t appear. Hold down the control key and click and drag from the indicator to File’s Owner at the top-left; choose the property name from the list that appears.

They the same – the colon-delimited version was introduced in macOS 10.10. Open and compile in a script editor, and you will see.

Yes.

Shane, I can’t express how much I appreciate your help! I finally was able to get it to work. As you noted, the progress indicator does continue to spin after the script completes, but I’ll search the forum for solutions as you noted. I’ll post the complete solution when I have it.

I did know that I needed to old down the control key and drag to link the interface. I had been clicking and dragging from the indicator, just as I had done for the button object. What actually worked, was clicking and dragging from the App Delegate to the Progress Indicator and then selecting the outlet. It is directionally specific!

It is insane that doing such simple things have been made so difficult. I love to hate AppleScript for the same reason. Apple has spent resources engineering all of this technology into their products, only to let it languish in the dark. I spent countless hours over a week searching the web to do this one simple thing!

It can be done in either direction – it’s just a bit different each way.

The script almost does what I want, except when the app launches, it shows the progress indicator on the initial app window.

I’ve attached a screen video that shows the app run through two cycles. The 1st starts from the initial screen as it appears upon launch. The second cycle shows how I’d like the app to work – no progress indicator until the button is clicked.

I tried many iterations with various code. Examples include: displayedWhenStopped, theWindow’s update_(), various progIndicator’s setHidden: and various handlers in an attempt to hide the progress indicator before the initial app screen displays.

In my initial post, I suggested disabling the button once it was pressed, but that isn’t needed since you cannot click the button while the progress indicator animates.

I’ve had no luck, and don’t have a clue how to proceed. Any suggestions?

use AppleScript version "2.4" -- Yosemite (10.10) or later
use framework "Foundation"
use scripting additions

script AppDelegate
	property parent : class "NSObject"
	
	-- IBOutlets
	property theWindow : missing value
    property progIndicator : missing value
    property setSpinnerHidden : missing value

    on startScript:sender
        
      progIndicator's setHidden:1
       
       my performSelector:"continueScript:" withObject:me afterDelay:0.3
        
    end startScript:
    
    
    on continueScript:sender
   
        -- SHOW progIndicator
        progIndicator's setHidden:0
        progIndicator's startAnimation:me
        
         -- do your stuff here -- START
         -- EXAMPLE CODE:
         set My_List to {"1", "2", "3"} as list
         repeat with i in My_List
             display dialog i giving up after 1
         end repeat
         -- do your stuff here -- END

          -- HIDE progIndicator
         progIndicator's setHidden:1
         progIndicator's stopAnimation:me

    end continueScript:
    

	on applicationWillFinishLaunching_(aNotification)
		-- Insert code here to initialize your application before any files are opened
	end applicationWillFinishLaunching_

    
	on applicationShouldTerminate_(sender)
		-- Insert code here to do any housekeeping before your application quits 
		return current application's NSTerminateNow
	end applicationShouldTerminate_

end script

None of your links are appearing.

Look at this thread: https://macscripter.net/viewtopic.php?id=46038

I’m not sure what is going on with the links. I’ve used the tags as directed on the help page: [url=/help.php#img]https://macscripter.net/help.php#img[/url]. They show as missing images in Safari, but you can still view them by holding down the Control key and choosing New Tab or New Window.

As you noted, no tags are shown at all with Firefox! The links are in Dropbox. I’ll repost below with and without tags as well as a different host. (After testing the Preview, it seems the issue is with Dropbox URLs.)

I had previously reviewed the thread @ https://macscripter.net/viewtopic.php?id=46038
and tried both tickleQueue() and fordEvent(). They didn’t seem to work, but it’s possible I did not implement them correctly. It’s hard to say, as I have tried so many things.

Just to reiterate, I’d like to remove the spinner image that appears when the app launches. It currently shows, then is hidden after the 1st click of the button and thereafter properly animates only after a button click.

Movie of current build of App:
Without Tags: https://point2acres.com/etc/progIndicator.mov
With Tags: https://point2acres.com/etc/progIndicator.mov

Remove all your setHidden: calls, and just uncheck Display When Stopped in Xcode.

%&#@! That was it, I can’t believe it was that simple! Shane, Thank you so much!

I ended up with a script that does what I want, albeit a stalling progress wheel. I also added a text string to the interface which could be used to provide text updates as the app does it’s processing. The actual script processes files in iTunes which seems to cause the progress wheel to stall. I tried many ways to force the animation to play smoothly, but without any success. Thank you to all who post and support this blog.

Movie of Demo Script App:


script AppDelegate
	property parent : class "NSObject"
	
	-- IBOutlets
	property theWindow : missing value
	property doProcess : missing value
	property enableDoProcess : missing value
	property iterateItems : missing value
	property Txt_Display : missing value
	property Txt_List : missing value
	property appLaunch : missing value
	property animateSpinner : missing value
	property setSpinnerHidden : missing value
	property myImage : missing value
	
	on doProcess:sender
		
		my performSelector:"animateSpinner" withObject:me
		
		tell appLaunch to setStringValue:"Loading Resources..."
		
		my performSelector:"iterateItems:" withObject:me afterDelay:0.1
		
		sender's setEnabled:false
		
	end doProcess:
	
	on iterateItems:sender
		
		setSpinnerHidden's setHidden:0
		animateSpinner's startAnimation:me
		
		set My_Counter to 0
		delay 1
		set Txt_List to {"I Say Hello", "You say Goodbye", "Hello, Hello", "Goodbye, Goodbye", ""}
		
		repeat with i in Txt_List
			
			set Txt_Display to i as string
			
			tell appLaunch to setStringValue:Txt_Display
			
			delay 1
			
		end repeat
		
		setSpinnerHidden's setHidden:1
		animateSpinner's stopAnimation:me
		enableDoProcess's setEnabled:true
		
	end iterateItems:
	
	on applicationWillFinishLaunching:aNotification
		-- Insert code here to initialize your application before any files are opened
	end applicationWillFinishLaunching:
	
	on applicationShouldTerminate:sender
		-- Insert code here to do any housekeeping before your application quits
		return current application's NSTerminateNow
	end applicationShouldTerminate:
	
end script