How exactly to use NSTimer in ASOC?

I read robdut’s post (http://macscripter.net/viewtopic.php?id=31515) about “delay” causing 100% CPU usage and that helped me track down many problems in my app. So I became interested in the methods mentioned in that post one being “sleep()” and the other being “NSTimer”. I tried sleep and it halt any progress bars updating text etc etc until finished. So I was wondering if someone could show me the ASOC syntax for setting up an NSTimer that gets called multiple times within a functions

the syntax using delay is currently formatted like this

on myFunction_(sender)
set textUpdate to "blah blah"
do shell script "......"
delay 2 (ideally would be replaced with NSTimer)
set textUpdate to "blah blah"
do shell script "......"
delay 2 (ideally would be replaced with NSTimer)
set textUpdate to "blah blah"
end myFunction_

You use a timer a bit differently – you set it up, and it calls a handler every time it fires. Something like this:

-- set up timer
current application's NSTimer's timerWithTimeInterval_target_selector_userInfo_repeats_(2, me, "timerFired:", "Whatever", true)

on timerFired_(theTimer)
	-- do your stuff
	-- To stop, use:
	-- theTimer's invalidate()
end timerFired_

Im a bit lost, how would I set it up so I can pause for 2 seconds in between things in 1 function, similar to the example I provided

I think the better way for this purpose is performSelector:withObject:afterDelay:

You can’t – the whole idea is not to pause your code (which can block the interface).

You can break it up easily

on myFunction_(sender)
set textUpdate to "blah blah"
do shell script "......"
performSelector_withObject_afterDelay_("myFunction2:", me, 2)
end myFunction_

on myFunction2_(sender)
set textUpdate to "blah blah"
do shell script "......"
end myFunction2_

If you want to run the shell script in background and pause the script while it runs you then can use NSTimer and check the pid etc…

on myFunction_(sender)
set textUpdate to "blah blah"
set pid to do shell script "......"
set myTimer to NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, me, "loopCheck:", missing value, true)
end myFunction_

on loopCheck_(sender)
--check for the pid in processes and if it is no longer there
--call myFunction2_(me) to proceed or clean up or whatever etc...
end loopCheck_

rob

Shane, what is the “Whatever” for? I would like to implement this into an app of mine.
Do we have to set theTimer to anything? What does incalidate() do?

Whatever you put there will be passed back if you call userInfo() on the timer later.

I should have said something like “set theTimer to…”

invalidate() kills the timer.

You can answer a lot of these questions yourself if you look in the documents for NSTimer class.

Actually, you don’t need to set the timer to anything, just saying NSTimer’s scheduledTimerWith… works ok - when the method you supply in the timer’s definition gets called the timer gets passed to it without needing a name.

I created a short program that creates some timers and shows how they behave. The nib just contains a label, a push button and a square button which are connected as indicated by the comments in the code:

[script TimersAppDelegate
property parent : class “NSObject”
property NSTimer : class “NSTimer”
property myButton : missing value --connected to a push button
property myLabel : missing value --connected to a label
property mySquare : missing value --connected to a square button
property x : 1
property plural : “”

on squarePress_(sender) --connected to the square button
	myLabel's setStringValue_("I pressed the square button")
	NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(5, me, "doSomething:", "Square button pressed", false)
	NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(30, me, "killProgram:", "", false)
end squarePress_

on buttonPress_(sender) --connected to the push button
	myLabel's setStringValue_("I pressed the push button")
	NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(5, me, "doSomething:", "Push button pressed", false)
end buttonPress_

on doSomething_(sender) --Not connected to anything.  A timer will call this method
	log sender's userInfo --this will print whatever is between the parentheses in the 4th parameter of the timer to the console window
	myLabel's setStringValue_("The timer fired " & x & " time" & plural)
	set x to x + 1
	set plural to "s"
end doSomething_

on killProgram_(sender)
	tell current application's NSApp to terminate_(me)
end killProgram_

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

on applicationShouldTerminate_(sender)
	myLabel's setStringValue_("The program is ending now")
	delay 2 --This delay is here just so you can see the change in myLabel before the window disappears
	return current application's NSTerminateNow
end applicationShouldTerminate_

end script
]

Notice that pushing either the push button or the square button starts a timer that calls the same method, doSomething:. You can push these buttons as many times as you want and notice both the immediate changes to myLabel as well as the 5 second delayed changes (and the log entries if you run it with the console window open).
Notice also, that pushing the square button also starts a timer that calls killProgram: which will cause the program to quit 30 seconds after you first push that button (after calling applicationShouldTerminate first).

I hope this helps.

It doesn’t work for me. I do performSelector_withObject_afterDelay_(“doSomething:”, me, 1) and it never does the function “doSomething:”, while on the first line, there is a LOGGING COMMAND! NOOO. D:

Dylan,

I’m not sure exactly what you’re doing, but this program works:

script SelectorAppDelegate
	property parent : class "NSObject"
	
	on doSomething_(sender)
		log "Something got run"
	end doSomething_
	
	on doSomethingElse_(sender)
		log "Something else got run"
	end doSomethingElse_
	
	on applicationWillFinishLaunching_(aNotification)
		performSelector_withObject_afterDelay_("doSomething:", me, 1)
		performSelector_withObject_afterDelay_("doSomethingElse:", me, 5)
	end applicationWillFinishLaunching_
	
end script

Ric

If I put a “do shell script” into this statement, it locks up my application until the shell script completes. How best is a shell script dealt with?

performSelector_withObject_afterDelay_((do shell script "stuff"), me, 1)

or

NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(0, me, (do shell script "stuff"), "", false)

It requires a handler name. Put the "do shell script’ stuff in its own handler, and include the name of the handler.

That’s true, but it can be useful if you want to be able to kill a timer somewhere else in your code.