4

I'm trying to create an NSArray with list values from an NSAppleEventDescriptor. There was a similar question asked some years back, although the solution returns an NSString.

NSString *src = [NSString stringWithFormat: @"return {\"foo\", \"bar\", \"baz\"}\n"];
NSAppleScript *exe = [[NSAppleScript alloc] initWithSource:src];
NSAppleEventDescriptor *desc = [exe executeAndReturnError:nil];

NSLog(@"%@", desc);

// <NSAppleEventDescriptor: [ 'utxt'("foo"), 'utxt'("bar"), 'utxt'("baz") ]>

I'm not sure what descriptor function I need that will parse the values into an array.

Community
  • 1
  • 1
l'L'l
  • 44,951
  • 10
  • 95
  • 146

2 Answers2

5

The returned event descriptor must be coerced to a list descriptor.
Then you can get the values with a repeat loop.

NSString *src = [NSString stringWithFormat: @"return {\"foo\", \"bar\", \"baz\"}\n"];
NSAppleScript *exe = [[NSAppleScript alloc] initWithSource:src];
NSAppleEventDescriptor *desc = [exe executeAndReturnError:nil];
NSAppleEventDescriptor *listDescriptor = [desc coerceToDescriptorType:typeAEList];
NSMutableArray *result = [[NSMutableArray alloc] init];
for (NSInteger i = 1; i <= [listDescriptor numberOfItems]; ++i) {
    NSAppleEventDescriptor *stringDescriptor = [listDescriptor descriptorAtIndex:i];
    [result addObject: stringDescriptor.stringValue];
}
NSLog(@"%@", result);
vadian
  • 274,689
  • 30
  • 353
  • 361
4

I wrote an extension to make this easier.

Note that atIndex() / descriptorAtIndex: has one-based indexes.

extension NSAppleEventDescriptor {

    func listItems() -> [NSAppleEventDescriptor]? {
        guard descriptorType == typeAEList else {
            return nil
        }

        guard numberOfItems > 0 else {
            return []
        }

        return Array(1...numberOfItems).compactMap({ atIndex($0) })
    }

}

Please comment or edit if any improvements can be made!

pkamb
  • 33,281
  • 23
  • 160
  • 191