bynkii (bynkii) wrote,

AppleScriptObjC odds and ends

Okay, so i've been adventuring with AppleScriptObjC, because a) FaceSpan 5 is in limbo, and will be for some time, (insert wailing noises here) and b) AppleScriptObjC is what i've been raging at Apple to give me for some time now, and it's not 100%, but it's pretty close. Any posts i put up for AppleScriptObjC will have "AppleScriptObjC" as the category, so you can find them easier.

My first application is really a port of a FS 5 application I wrote that's a WiFi signal analyzer. eventually, it will show you stats, let you automatically track those stats over time, refreshing once per second, save that data to a new file, or append to an existing file, and show you a live graph of signal vs. noise in the app window. I had all this working in FS 5, so i aim to get it all working in ASAppleScriptObjC.

First, a huge, huge, huge thank you to both Shane Stanley and Craig Williams. The both of them have been a huge help to me in this, and the community is far better for having them in it.

Second, if you haven't yet gone, run to MacScripter's AppleScriptObjC forums, it's a hell of a resource, and Craig has a great set of tutorials that were, and are a monstrous help to me.

In one sense, my refusal to deal with the unending limitations of ASS have been a help, as I don't have any bad habits to break from that direction. Since I don't know Objective C, I don't have to deal with those differences either. However, the lack of ObjC knowledge is a bit of a pain in the keister when reading Apple developer docs, although not as much as I thought it might be, thanks to Craig's tutorials.

So, some quick shots that I learned:
  • Don't rely on Xcode or anything else to tell you when you're missing a framework. You can reference CoreWLAN all day long, and you won't know you forgot to add the framework until you try to use some of the methods or properties. boo.yah

  • The Xcode debugger still doesn't work for beans with AppleScript, and even what little it worked for ASS, was too complicated to set up. There's two issues here. First, the way I want it to work is I set a breakpoint, and when it hits that breakpoint, it stops and i can step from there. I don't know why this doesn't work this way, don't care, because while i can dig up the email that tells me how to do it, seriously, this shouldn't be that hard. Enable breakpoint, stop on breakpoint.

    The other issue of course is that Xcode's debugger is GDB, and it's simply not designed to work, nor shall it ever work well with a higher-level language with dynamic syntax like AppleScript. I really wish Apple would throw a gob of money at Mark Aldritt so that he could write the AppleScriptObjC debugger implementation for Apple. He's the only one to ever really get it right.

  • Join the AppleScriptObjC list. Less noise than the ASS list, so it's quite useful if you don't really care about ASS, which I don't.

  • Before I use a class, I make sure to create the property for it, so lots of property NSTimer : class "NSTimer" kinds of things. It's pretty handy as a habit.

  • Setting up and using stuff in Interface Builder really is as easy as the tutorials make it seem.

  • Learning how to translate ":" to "_" is a pain in the butt, but important. For example, in Objective C, you have:

    (void)setNameFieldStringValue:(NSString *)value

    The AppleScriptObjC version is:

    theSavePanel's setNameFieldStringValue_("File.txt")

    That's pretty easy. Where it gets tricky is when you have stuff like this example from NSTimer:

    (NSTimer *)scheduledTimerWithTimeInterval:(NSTimeInterval)seconds target:(id)target selector:(SEL)aSelector userInfo:(id)userInfo repeats:(BOOL)repeats

    The AppleScriptObjC version:

    NSTimer's scheduledTimerWithTimeInterval_target_selector_userInfo_repeats_(1, me, "timerFired:", "", true)

    Took me a few readthroughs to figure out that with AppleScriptObjC, that first parameter was a bit odd, and that i should see it as being, (assuming the method existed with only an interval parameter):

    NSTimer's scheduledTimerWithTimeInterval_(1)

    Once I grokked that there's always an underscore for every colon, even if it's just a trailing colon, things got a lot easier.

  • Another thing about NSTimer that I probably would have never realized on my own, is that to use NSTimer in this way, that selector bit should be read as "create another handler for theTimer that has the same name as the selector, and that this is where all the code for the timer will run:

    on timerFired_(thetimer)

    It's also a little odd, to me at least, to have the code to kill the timer in the same handler as the timer's functional code, but okay, sure. (there's still a bit of "take it on faith" with regard to NSTimer for me at this stage.)

  • "my" is very important. Say for example, you have a button (or two) that are disabled by default, and you want them to become enabled when another checkbox is clicked. Well, you set them as disabled in Interface Builder, so your initial state is set. Then you want them to be enabled when that checkbox is enabled. You might want to do this:

    on saveToFile_(sender)
         if sender's intValue() is 1 then
              createNewDataButton's setEnabled_(true)
              appendToExistingDataButton's setEnabled_(true)
         else if sender's intValue() is 0 then --if you're de-checking the checkbox
              createNewDataButton's setEnabled_(false)
              appendToExistingDataButton's setEnabled_(false)
         end if
    end saveToFile_

    and that will work, sort of. The buttons will enable and disable, but even after you wire them up to code, they won't DO anything when you click them. They know they're enabled, the application doesn't. For that bit to work, you need "my":

    on saveToFile_(sender)
         if sender's intValue() is 1 then
              my createNewDataButton's setEnabled_(true)
              my appendToExistingDataButton's setEnabled_(true)
         else if sender's intValue() is 0 then --if you're de-checking the checkbox
              my createNewDataButton's setEnabled_(false)
              my appendToExistingDataButton's setEnabled_(false)
         end if
    end saveToFile_

    Now, when you click the newly enabled buttons, stuff will happen. Stuff happening is good.

  • Objective C may tell you to use YES and NO for BOOLs. AppleScriptObjC wants 1 and 0, and don't you forget it.

  • Just because AppleScript is case-insensitive, Objective C is not, and will mess with your head until you realize that.

  • I really wish Apple's IT documentation was as good as its developer docs.

That's enough for now, I'll start going through some of the actual code stuff I'm working on later.
  • Post a new comment


    default userpic

    Your reply will be screened

    Your IP address will be recorded 

    When you submit the form an invisible reCAPTCHA check will be performed.
    You must follow the Privacy Policy and Google Terms of use.