title: How do I successfully delete an item from keychain in OS X?
body: <p>How do I successfully delete an item from keychain in OS X? This is what I have so far, but it is failing at the <code>SecItemDelete</code> call. Do I need to specify some additional attributes in the query dictionary or something? I can successfully insert key-value pairs into the keychain by doing similar operations. </p>
  
  <pre><code>#define DELETE_SIZE 3
  bool delete_key_keychain( const char *cKeyValue, SecKeychainRef keychain) {
      if ( !keychain)
          return false;
  
      // Convert to CFString.
      CFStringRef keyValue = CFStringCreateWithCString( NULL, cKeyValue, kCFStringEncodingUTF8);
      if ( !keyValue)
          return false;
  
      // Specify query parameters.
      const void *keys[DELETE_SIZE] = {
          kSecClass,
          kSecUseKeychain,
          kSecAttrAccount
      };
      const void *values[DELETE_SIZE] = {
          kSecClassGenericPassword,
          keychain,
          keyValue
      };
  
      // Create query.
      CFDictionaryRef query = CFDictionaryCreate( NULL, keys, values, GET_SIZE, NULL, NULL);
      if ( !query) {
          CFRelease( keyValue);
          return false;
      }
  
      // Run query.
      OSStatus status = SecItemDelete( query);
      CFRelease( query);
      CFRelease( keyValue);
  
      return status == errSecSuccess;
  }
  </code></pre>
  
  <p>Update: According to this <a href="http://useyourloaf.com/blog/2010/04/28/keychain-duplicate-item-when-adding-password.html" rel="nofollow">link</a>, I need to set the <code>kSecAttrService</code> property in the query. As a result, I started using <code>SecKeychainFindGenericPassword</code> and <code>SecKeychainItemDelete</code>. This will delete the password successfully, however subsequently adding a different password for the same account can cause crashes. Therefore, I've started using <code>SecKeychainItemModifyAttributesAndData</code> to modify the password and don't delete passwords. I believe this instability might be due to caching that the API performs. </p>