Problem is, if the user has typed in the wrong username and password, it takes three minutes before it times out. Not good. During this time, the interface is completely unresponsive
What I would like to do is to kick off this command but instantly regain control.
I’ve got stefan’s book in front of me, specifically page 210, but it concentrates on shell commands not regular instructions. Any ideas?
Unfortunately that doesn’t solve the problem by itself. The method will be called on a different thread, but the application’s single instance of AppleScript will be blocked until it returns. This is one of the areas where ASObjC falls short.
Probably the only solution is to use an Objective-C helper class a and put the call in a method there. Then performSelectorInBackground_withObject_ should solve the problem.
And Rob: NSTask is for running processes, not methods.
– Not Stefan, but after two days’ flying to get home, I had to check…
Firstly, apologies on the naming issue It had been a long week!
I’d been thinking about this all weekend, and couldn’t wait to get to work to try out my thoughts:
My thinking was this:
set theTimer to current application's NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(15, me, "timerFired:", "Whatever", true)
as per Shane’s book!
However, I do recall ASOC being single instance
So, Shane… If you have a “hello world” type example of this or ideas on how I could call the following in Objective-C helper class:
current application's NSThread's sleepForTimeInterval_(15)
set currentInterface to CWInterface's interface()
currentInterface's setPower_error_(FALSE, missing value)
current application's NSThread's sleepForTimeInterval_(5)
currentInterface's setPower_error_(TRUE, missing value)
In a nutshell:
With the wrong credentials, currentInterface’s associateToEnterpriseNetwork_identity_username_password_error_(myNetwork, missing value, myUser, myUserPW, missing value) hogs the single instance of the ASOC until it times out (which is around 3 minutes)
I’d like to kick off the code above, but at the same time, connect to my wifi network
I’m very much appreciative of the help that’s already been given with my various wifi issues. This should be the last issue
Sorry for beeing so unclear and mixing up names, I actually meant to call detachNewThreadSelector_toTarget_withObject_ of NSThread class which is the same as performSelectorInBackground method from another object than self. Of course the target object has to be an objective-C object/class. This way you don’t need to create an Objective-C helper class.
p.s. how was the Netherlands?
Edit: with some example code:
The Objective-C class to test with named sleeper (just to simulate a long command). I’m using class methods because there are no instance variables needed in this method. So we don’t need to allocate this object later in ASObjC.
property sleeper : class "sleeper"
property NSThread : class "NSThread"
script PerformSelectorInBackgroundAppDelegate
property parent : class "NSObject"
property startSleepBtn : missing value --connects to a button in the window
on startSleep_(sender)
log "Start Thread"
set myThread to NSThread's detachNewThreadSelector_toTarget_withObject_("startSleeping:", sleeper, 500000)
delay 2.5
log "Continue"
end startSleep_
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
In my log it will appear nicely, The first 2.5 seconds my button hangs, the next 2.5 seconds it will not while the thread is still running as you will see in your log view. My results are as expected:
You may still be able to use performSelectorInBackground_withObject_ if the selector is in an Objective-C superclass of the AS class – the key thing is that the selector must be Cocoa/Objective-C, not ASObjC, so that whatever happens can’t block the single instance of AppleScript.
Whatever, I think the OP was originally after an Obj-C class containing a method like this (untested):
In the case of a superclass, you’d probably make it an instance method. The withObject_ parameter would be an AS record like {myNetwork:whatever, userName:“Fred”, userPassword:“1234”, sendingObject:me}, and it would have a handler methodSucceeded_(successFlag) that would be called with the result.
At least, I think that would work…
The whole trip was wonderful, if exhausting, thanks. Lots of walking; my OV-chipkaart barely got used…
Well I think we’re on the same wavelength but I was thinking to send associateToEnterpriseNetwork call to the thread directly (I know the multiple parameter issue, but there is an workaround for that: NSInvocation).
So, I’m guessing that I create a dictionary object first in ASOC, such as :
tell current application's NSDictionary to set myDict to dictionaryWithObjects_forKeys_({WiFiInterface:currentInterface, ssid:myNetwork, identity:missing value, userName:MyUser, userPassword:MyUserPW, errormsg:missing value})
Then, we call the Cocoa object (that bit is a little fuzzy). Something along the lines of:
set myThread to NSThread's detachNewThreadSelector_toTarget_withObject_("connectToWifi:", myDict)
I know that under the +(void)doStuffWith:(NSDictionary *)dict I need to declare the items
Am I on the right track?
With regards to what goes where: I’d much rather have the associateToEnterpriseNetwork within the C class. This allows the UI to be responsive (indeterminate progress bars. etc)
As you’re passing it as an argument, you can just use the AS record.
Your first argument should match the method name, so “doStuffWith:” in this case, and you left out a target, which in this case will be “current application’s ”.
property connectWiFi : class "connectWiFi"
property NSThread : class "NSThread"
script AppDelegate
property parent : class "NSObject"
property CWInterface : class "CWInterface"
my ASOC code
set WiFiNetwork to "bobsnetwork"
set CECUser to "bob"
set CECUserPW to "bobspassword"
set currentInterface to CWInterface's interface()
set networks to currentInterface's scanForNetworksWithName_error_(WiFiNetwork, missing value)
set myNetwork to networks's anyObject()
log "before dict worked"
tell current application's NSDictionary to set myDict to dictionaryWithObjects_forKeys_({currentInterface, myNetwork, CECUser, CECUserPW})
log "dict worked"
set myThread to NSThread's detachNewThreadSelector_toTarget_withObject_("current application's connectWifi:", myDict)
Issues:
// get currentInterface however that’s done, then…
BOOL result = [[dict valueForKey:@“currentInterface”] associateToEnterpriseNetwork:[dict valueForKey:@“myNetwork”] identity:nil username:[dict valueForKey:@“userName”] password:[dict valueForKey:@“userPassword”] error:NULL]; has a small issue with “unused variable ‘result’” I’m guessing that’s more for indication rather than an error
It builds (which was a shock to me!)
When running, I get the following issue:
2013-05-14 11:18:27.449 SetupBob[68100:303] before dict worked This isn’t an issue, just logging
2013-05-14 11:18:27.451 SetupBob[68100:303] CMSAJourney:User selected Wi-Fi: encountered an error: I have this in a try and capture any errors method dictionaryWithObjects:forKeys: expected at least 2 arguments, got 1.
Takes 90 seconds for the cocoa class to log a result, but we’ve already got past that by advising the user, etc, and they’ve then typed in new credentials
Again, I can’t offer enough thanks for the help on here