Scripting Bridge Release Notes

This document covers new and updated information for Scripting Bridge. Conceptual and reference information formerly in this document has been moved to Scripting Bridge Programming Guide.

Contents:

10.6 Changes

Error Handling

Instance methods in Scripting Bridge send Apple events to the target application, which may fail for a variety of different reasons, many of them not detectable beforehand. In previous versions, Scripting Bridge handled failed events by calling the delegate method eventDidFail:withError:, the default implementation of which threw an exception. This reflected AppleScript’s usage, but in Cocoa, exceptions are reserved for programming errors, not run-time errors. Therefore, OS X v10.6 changes the error handling protocol. When an event fails, an NSError object will be attached to the SBObject instance that sent the event, which you can get using the new -lastError method:

@interface SBObject (ErrorHandling10_6)
- (NSError *) lastError;
@end

If the program set a delegate object, it will be called after setting lastError, and the originating method will return nil or 0 depending on its return type.

Because the error is only attached to the instance that sent the event, chained expressions will need to be rewritten if you want to report errors. Consider attempting to get the name of the current track in iTunes, which will fail if there is no current track. You could write this naively, ignoring the error:

iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
name = [[iTunes currentTrack] name];
if (name) NSLog(@"current track is %@", name);

This works, because name will return nil on failure, but the error has been effectively lost, because it was attached to the temporary object returned by [iTunes currentTrack]. To get at the error, you would have to rewrite the code slightly to hold a reference to the intermediate SBObject, shown here using track:

iTunes = [SBApplication applicationWithBundleIdentifier:@"com.apple.iTunes"];
track = [iTunes currentTrack];
name = [track name];
if (name)
    NSLog(@"current track is %@", name);
else {
    NSError *error = [track lastError];
    NSLog(@"couldn't get current track because %@", [error localizedDescription]);
}

Predicate Handling

-[SBElementArray filteredArrayUsingPredicate:] does not directly support everything NSPredicate can do, because it must turn the predicate into an Apple event, which has fewer features. In previous versions, if it received a predicate that could not be represented as an Apple event, it would fall back to -[NSArray filteredArrayUsingPredicate:]. However, this gave inconsistent results: depending on the predicate, it might return either an NSArray or an SBElementArray, and the performance could be wildly different.

In v10.6, -[SBElementArray filteredArrayUsingPredicate:] will fail with an exception if given a predicate it cannot handle. If you cannot rewrite the predicate without the unsupported bits, you can emulate the old behavior by using -get to get an NSArray, and then use -filteredArrayUsingPredicate: on that:

filtered = [[SomeApp someObjects] get] filteredArrayUsingPredicate:complexPredicate];

For best performance, separate out the parts that SBElementArray can handle into another predicate and filter that first, so the second predicate will have to examine fewer objects:

firstPass = [[[SomeApp someObjects] filteredArrayUsingPredicate:simpleBits] get];
filtered = [firstPass filteredArrayUsingPredicate:complexBits];

For compatibility, applications linked on OS X v10.5 will still get the old behavior. For scripts using Scripting Bridge via an Objective-C bridge such as PyObjC or RubyCocoa, the relevant “application” is the interpreter. If the interpreter was built on OS X v10.6, as python(1) and ruby(1) are, then the script gets the new behavior.

Bug Fixes and Enhancements

NSDictionary-AERecord translation now handles user-defined keys (as opposed to keys defined by the application scripting interface). [5525649]

-[SBElementArray addObject:] now works better with non-Cocoa applications. [5585347]

A number of memory leaks have been fixed. [5856221]

Scripting Bridge no longer prints warnings about malformed scripting interfaces when creating an SBApplication object. [5964420]

sdp(1) has improved error messages, and flags warning messages as warnings. [5649633]

10.5.6 Changes

Application-specific methods that return BOOL now work correctly on PowerPC systems. [5525649]

Thread Safety

Using multiple threads with Scripting Bridge may give perceived or actual performance advantages. In particular, a remote application may take a while to respond to a message, and your application should stay responsive to user input while it waits. Scripting Bridge may be used with multiple threads, given a few guidelines.

This information applies to all versions of Scripting Bridge.