title: Returning Objective-C object with Core Foundation attribute
body: <p>I have a method that returns an NSArray of a custom object called "Credential" that has two properties: an NSString and a CFDataRef. </p>
  
  <p>As you have noticed the object has two types of properties, a NS Objective-C property and a Core-Foundation property.</p>
  
  <p>The object is initialized at every interation loop as it fills the NSArray like this:</p>
  
  <pre><code>cred = [[Credential alloc] init];
  cred.cn = [NSString stringWithString:(__bridge NSString *)(summary)];
  cred.serialNumber = CFDataCreateCopy(kCFAllocatorDefault, serialNumber);
  </code></pre>
  
  <p>When I run the analyzer I'm getting the message:</p>
  
  <pre><code>Object leaked: allocated object is not referenced later in this 
  execution path and has a retain count of +1
  </code></pre>
  
  <p>I'm assuming this warning happens because I'm initializing a CF object and returning from the method without releasing it, yet the new responsible for releasing the object should
  be the code calling the method. </p>
  
  <p>Where should I call the CFRelease of the CFDataRef property of the Credential class?</p>
  
  <p><strong>EDIT:</strong></p>
  
  <p>I'm using ARC so I leave to him the responsibility of releasing the NSString (cred.cn). About the CFDataRef (cred.serialNumber), though, I'm not releasing it, since I'll need it later from another class and part of the code. Then, I'm not sure how to manage it. Does ARC release it when the object "Credential" is disposed? If not, can I overwrite the dealloc method of Credential to do the CFRelease of serialNumber there?</p>
  
  <p>Here's the full method that initializes and returns the NSArray of Credential objects:</p>
  
  <pre><code>- (NSArray *) retrieveIdentities
  {
      CFArrayRef identities = NULL;
      NSMutableArray *returnIdentities = nil;
      OSStatus sanityCheck = NULL;
  
      const void *keys[] = {kSecClass, kSecMatchLimit, kSecReturnRef, kSecReturnData, kSecReturnAttributes};
      const void *values[] = {kSecClassIdentity, kSecMatchLimitAll, kCFBooleanTrue, kCFBooleanTrue, kCFBooleanTrue};
      CFDictionaryRef query = CFDictionaryCreate(NULL, keys, values, sizeof(values)/sizeof(const void *), NULL, NULL);
  
      sanityCheck = SecItemCopyMatching(query, (CFTypeRef *)&amp;identities);
  
      if (query)
          CFRelease(query);
      if (sanityCheck == errSecItemNotFound)
          return nil;
      if (sanityCheck != noErr)
          @throw [[KeychainException alloc] initWithName:@"KeychainException" reason:@"ERROR_LISTING_IDENTITIES" userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithLong: sanityCheck], @"osstatus", nil]];
  
      CFDictionaryRef result = NULL;
      CFStringRef summary = NULL;
      SecCertificateRef certificate = NULL;
      CFDataRef serialNumber = NULL;
      Credential *cred = nil;
      CFIndex resultCount = CFArrayGetCount(identities);
  
      returnIdentities = [[NSMutableArray alloc] init];
  
      for (CFIndex i = 0; i&lt;resultCount; i++)
      {
          result = CFArrayGetValueAtIndex(identities,i);
          SecIdentityRef identity = (SecIdentityRef) CFDictionaryGetValue(result, kSecValueRef);
  
          if ((sanityCheck = SecIdentityCopyCertificate(identity, &amp;certificate)) != noErr)
               @throw [[KeychainException alloc] initWithName:@"KeychainException" reason:@"ERROR_EXTRACTING_CERTIFICATE" userInfo:[NSDictionary dictionaryWithObjectsAndKeys:[NSNumber numberWithLong: sanityCheck], @"osstatus", nil]];
  
          CFTypeRef keyClass = CFDictionaryGetValue(result, kSecAttrKeyClass);
          if ([[(__bridge id)keyClass description] isEqual:(__bridge id)(kSecAttrKeyClassPrivate)])
          {
              summary = SecCertificateCopySubjectSummary(certificate);
              serialNumber = CFDataCreateCopy(NULL, CFDictionaryGetValue(result, kSecAttrSerialNumber));
              cred = [[Credential alloc] init];
              cred.cn = [NSString stringWithString:(__bridge NSString *)(summary)];
              cred.serialNumber = CFDataCreateCopy(kCFAllocatorDefault, serialNumber);
              [returnIdentities addObject:cred];
  
              if (summary)
                  CFRelease(summary);
  
              if (serialNumber)
                  CFRelease(serialNumber);
          }
      }
  
      if (certificate)
          CFRelease(certificate);
  
  
      return returnIdentities;
  }
  </code></pre>