title: Getting an AppleScript property of an NSAppleEventDescriptor
body: <p>I'm trying to use some Apple Events in my Cocoa project to get access to the Terminal application. I did not want to use embedded AppleScripts or any compiled scripts, so I started looking into the <code>NSAppleEventDescriptor</code>.</p>
  
  <p>I have succeeded in creating a new window using the <code>do script</code> command, and I have succeeded to get the window from the return value. The only thing I want to do right now is get a property of that window.</p>
  
  <p>I had now idea how to get such a property, so I started googling. Unfortunately, there aren't a lot of good examples how to use Apple Events, and I failed to find what I was looking for.</p>
  
  <p>So I started digging deeper. And the first thing I did was looking for the code for the <code>get</code> command in the Terminal <code>.sdef</code> file. I failed to find it, so I did a <code>grep</code> on my <code>/System/</code> directory and I found <code>/System/Library/Frameworks/AppleScriptKit.framework/Versions/A/Resources/AppleScriptKit.sdef</code>. I apparently found the core of the AppleScript syntax. That file did indeed have the <code>getd</code> four character code.</p>
  
  <p>So now I know I have to use the <code>getd</code> event from the Core Suite. However, the argument to that get-command was an <code>objectSpecifier</code>. I have searched high and low for an example that uses <code>kAEGetData</code>. But I have failed to find any code from which I could learn anything.</p>
  
  <p>So I am asking here: <b>how do I build such an <code>objectSpecifier</code> descriptor?</b></p>
  
  <p>This is what I've already got:</p>
  
  <p><strong>Code to create and get the tab descriptor</strong></p>
  
  <pre><code>NSAppleEventDescriptor *createEvent;
  NSAppleEventDescriptor *scriptParam;
  AppleEvent aeReply;
  OSErr err;
  
  /* Make the do script event */
  createEvent = [NSAppleEventDescriptor 
                 appleEventWithEventClass:kAECoreSuite 
                 eventID:kAEDoScript 
                 targetDescriptor:_applicationDescriptor 
                 returnID:kAutoGenerateReturnID 
                 transactionID:kAnyTransactionID];
  if(createEvent == nil) {
      NSLog(@"%s Failed to create a do script event",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  /* Make script parameter */
  scriptParam = [NSAppleEventDescriptor descriptorWithString:@"echo Hello World"];
  if(scriptParam == nil) {
      NSLog(@"%s Failed to create the script parameter",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  /* Set parameter */
  [createEvent setParamDescriptor:scriptParam forKeyword:keyDirectObject];
  
  /* Send event */
  err = AESendMessage([createEvent aeDesc], &amp;aeReply, 
                      kAEWaitReply | kAENeverInteract, kAEDefaultTimeout);
  if(err != noErr) {
      NSLog(@"%s Failed to send the create command", 
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  /* Retrieve information */
  {
      /* SEE BELOW TO SEE HOW I GET THE WINDOW DESCRIPTOR */
  }
  </code></pre>
  
  <p><strong>Now I try and succeed in getting the window of that tab</strong></p>
  
  <pre><code>   // NSAppleEventDescriptor *ansr is set to the result of the code above
  
  NSAppleEventDescriptor *mainObj;
  NSAppleEventDescriptor *desiredClass;
  NSAppleEventDescriptor *window;
  
  mainObj = [ansr paramDescriptorForKeyword:keyDirectObject];
  if([mainObj descriptorType] != typeObjectSpecifier) {
      NSLog(@"%s Main object was not an object specifier",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  desiredClass = [mainObj paramDescriptorForKeyword:keyAEDesiredClass];
  if([desiredClass typeCodeValue] != kAETerminalTab) {
      NSLog(@"%s Main object's desired class was not a Terminal tab",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  window = [mainObj paramDescriptorForKeyword:keyAEContainer];
  if(window == nil) {
      NSLog(@"%s Couldn't get container of the tab",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  desiredClass = [window paramDescriptorForKeyword:keyAEDesiredClass];
  if([desiredClass typeCodeValue] != cWindow) {
      NSLog(@"%s The container of the tab was not a window",
            __PRETTY_FUNCTION__);
      return nil;
  }
  
  return window;
  </code></pre>
  
  <p><strong>And now I fail in getting, let's say, the bounds property</strong></p>
  
  <pre><code>// _windowDescriptor is the result of the code above
  
  NSAppleEventDescriptor *getEvent;
  NSAppleEventDescriptor *prop;
  AppleEvent aeReply;
  NSAppleEventDescriptor *reply;
  FourCharCode propName;
  OSErr err;
  
  propName = keyAEBounds;
  
  /* Create get event */
  getEvent = [NSAppleEventDescriptor
              appleEventWithEventClass:kAECoreSuite 
              eventID:kAEGetData 
              targetDescriptor:_windowDescriptor 
              returnID:kAutoGenerateReturnID 
              transactionID:kAnyTransactionID];
  if(getEvent == nil) {
      NSLog(@"%s Failed to create a get event",
            __PRETTY_FUNCTION__);
      return NSZeroRect;
  }
  
  /* Get property */
  prop = [NSAppleEventDescriptor
          descriptorWithDescriptorType:typeProperty 
          bytes:&amp;propName length:sizeof(propName)];
  if(prop == nil) {
      NSLog(@"%s Failed to create the bounds property",
            __PRETTY_FUNCTION__);
      return;
  }
  
  /* Set parameter */
  [getEvent setParamDescriptor:prop forKeyword:keyDirectObject];
  
  /* Exectue */
  err = AESendMessage([getEvent aeDesc], &amp;aeReply, 
                      kAEWaitReply | kAENeverInteract, kAEDefaultTimeout);
  if(err != noErr) {
      NSLog(@"%s Failed to send the get message",
            __PRETTY_FUNCTION__);
      return;
  }
  
  reply = [[NSAppleEventDescriptor alloc] initWithAEDescNoCopy:&amp;aeReply];
  [reply autorelease];
  
  NSLog(@"Bounds: %@", reply);
  </code></pre>
  
  <p>As explained, the above code works, just until the last block.<br>
  Thank you in advance for the help.</p>