NSAppleScript question

  • Greetings,
    I'm currently bashing my head against the wall (rather painfully)
    trying to get NSAppleScript functioning the way I want.
    How I currently have this setup is there are several applescript
    scripts that are located in the resources section of the main bundle
    and I am trying to load them with the following code.

    NSDictionary *loadError = [[NSDictionary alloc] init];
    NSDictionary *error = [[NSDictionary alloc] init];
    NSAppleEventDescriptor *returnDescriptor = nil;
    NSString *scriptLocation = [[NSString alloc] initWithFormat:@"%@/%@",
    [[NSBundle mainBundle] resourcePath],
    @"RSITunesLaunchApplescript.scpt"];
    NSURL  *fileURL = [[NSURL alloc] initWithString:scriptLocation];
    NSFileManager *manager = [NSFileManager defaultManager];
    NSAppleScript *scriptObject = nil;

    // Create the script here
    if([manager fileExistsAtPath:scriptLocation]) {
      scriptObject = [[NSAppleScript alloc] initWithContentsOfURL:fileURL
    error:&loadError];

      // Both scriptObject and loadError are null for some unknown reason

      if(scriptObject == nil) {
      NSLog(@"The error is: %@", [loadError
    valueForKey:NSAppleScriptErrorMessage]);
      }
    }

    NSLog(@"%@", scriptObject);

    // Run the script
    NSLog(@"executing script");
    if(scriptObject != nil)
      returnDescriptor = [scriptObject executeAndReturnError: &error];

        if ([returnDescriptor descriptorType]) {
            NSLog(@"script executed sucessfully.");
        } else {
            NSLog(@"Script execution has gone a bit pear shaped: %@",
    [error objectForKey: @"NSAppleScriptErrorMessage"]);
        }

    What is happening is that the NSFileManager is correctly showing the
    existance of the applescript file though when I use NSAppleScript
    initWithContentsOfURL: error: I get both objects becoming nil.

    As far as the configuration for the project, I'm using XCode 3,
    Leopard and have Garbage Collection turned on.

    Any help would be greatly appreciated as my head is rather sore.

    Thanks,
    Matthew Delves
  • On 02/02/2008, at 7:59 PM, Devraj Mukherjee wrote:


    Thanks for that. I'm kinda feeling a bit stupid as after changing the
    code so that it created the NSURL object properly using NSURL
    fileURLWithPath it now works.

    Again, much thanks.

    Matthew Delves
  • On Feb 2, 2008, at 09:12, Matthew Delves wrote:

    > NSDictionary *loadError = [[NSDictionary alloc] init];

    You leak a dictionary here. Correct:

    NSDictionary *loadError = nil;

    > NSDictionary *error = [[NSDictionary alloc] init];

    Same issue, same correction.

    > NSAppleEventDescriptor *returnDescriptor = nil;
    > NSString *scriptLocation = [[NSString alloc] initWithFormat:@"%@/%
    > @", [[NSBundle mainBundle] resourcePath],
    > @"RSITunesLaunchApplescript.scpt"];

    There is a method to find path of resources:

    NSString *scriptPath = [[NSBundle mainBundle]
    pathForResource:@"RSITunesLaunchApplescript" orType:@"scpt"];

    Note that I renamed the variable to scriptPath. There is no such
    thing as location in Cocoa, but there are many methods that use "path".

    Now check that path:

    if (sciptPath == nil)
      // There is no point to continue. Fail as soon as you  can.

    > NSURL        *fileURL = [[NSURL alloc] initWithString:scriptLocation];

    Use fileURLWithPath:

    > NSFileManager *manager = [NSFileManager defaultManager];

    You don't need the file manager.

    > NSAppleScript *scriptObject = nil;

    Aren't all those objects objects? What's wrong with "script"?

    >
    > // Create the script here

    You don't need that check, pathForResources already detected the file.

    > if([manager fileExistsAtPath:scriptLocation]) {

    > scriptObject = [[NSAppleScript alloc]
    > initWithContentsOfURL:fileURL error:&loadError];
    >
    > // Both scriptObject and loadError are null for some unknown reason
    >
    > if(scriptObject == nil) {
    > NSLog(@"The error is: %@", [loadError
    > valueForKey:NSAppleScriptErrorMessage]);

    Use objectForKey: to access a dictionary values.

    This is a good place to bail out from this method. There is no point
    in continuing and checking again if the script is nil.

    > }
    > }
    >
    > NSLog(@"%@", scriptObject);

    > // Run the script
    > NSLog(@"executing script");
    > if(scriptObject != nil)
    > returnDescriptor = [scriptObject executeAndReturnError: &error];
    >
    > if ([returnDescriptor descriptorType]) {

    The correct test for success is:

    if (returnDescriptor != nil)

    > NSLog(@"script executed sucessfully.");
    > } else {
    > NSLog(@"Script execution has gone a bit pear shaped: %@",
    > [error objectForKey: @"NSAppleScriptErrorMessage"]);
    > }

    What's wrong with pear shape?

    Best Regards,

    Nir Soffer