3

When I build and analyze my project on XCode, I obtain a 'warning' on the following line:

NSString *contactEmail = (NSString *)ABMultiValueCopyValueAtIndex(emailInfo, 0);

The message is: Potential leak on object allocated on line ... and stored into contactEmail.

Is there any error on that line?

UPDATE

I get the same 'warning' with this line of code:

ABMultiValueRef emailInfo = ABRecordCopyValue(person, kABPersonEmailProperty);

But here, I can't do this:

[emailInfo release];

I'm developing for iPhone.

nall
  • 15,899
  • 4
  • 61
  • 65
VansFannel
  • 45,055
  • 107
  • 359
  • 626

2 Answers2

7

ABMultiValueCopyValueAtIndex is a "Copy" function, which follows the "Create Rule". You need to call CFRelease to release it after finish using it.

NSString *contactEmail = (NSString *)ABMultiValueCopyValueAtIndex(emailInfo, 0);
...
if (contactEmail != nil)
  CFRelease((CFTypeRef) contactEmail);
kennytm
  • 510,854
  • 105
  • 1,084
  • 1,005
  • 1
    Since the object is being used as an NSString, it's much more natural to send a release or autorelease message to it than to check for nil, cast it back again and call CFRelease() – Jason Coco Apr 14 '10 at 14:31
  • The object *is* an `NSString`. – Williham Totland Apr 14 '10 at 14:42
  • 2
    @Williham: (1) `ABMultiValueCopyValueAtIndex` returns CoreFoundation objects, which may be a CFString, or other stuff e.g. CFNumber. In fact OP should check before assuming the result is a string, but that's rare case. (2) A CFString can be toll-free-bridged to use NSString methods. A CFString is part of the class-cluster of NSString, but the class is actually NSCFString. @Jason: I prefer to use CF API for CF stuff, but yeah your suggestion also works. – kennytm Apr 14 '10 at 14:46
  • I've updated my question. I also have the same problem with **ABMultiValueRef emailInfo = ABRecordCopyValue(person, kABPersonEmailProperty);** – VansFannel Apr 14 '10 at 14:49
  • 2
    @KennyTM: (1) Obviously, "The object *is* an `NSString`, assuming it is a `CFString`.". Given a name like `emailInfo`, this seems somewhat likely. (2) An `NSCFString` is also an `NSString`; and saying that CFString *can* be toll-free-briged makes it seem optional. It *is* bridged. – Williham Totland Apr 14 '10 at 14:50
  • 1
    @Vans: `CFRelease(emailInfo);` – kennytm Apr 14 '10 at 14:51
  • @KennyTM: I prefer that too, but the OP is obviously preferring to use the Foundation classes, so it is more natural to treat the object as a Foundation class, that's all I was saying. – Jason Coco Apr 14 '10 at 16:23
1
  1. The cast is somewhat pointless.
  2. The line might leak, unless you release or autorelease it somewhere.

Edit: For brevity:

NSString *contactEmail = [(NSString *)ABMultiValueCopyValueAtIndex(emailInfo, 0) autorelease];

(The cast might still be pointless, I'm unsure as to how the compiler would handle trying sending a message directly to a CFTypeRef.)

Williham Totland
  • 28,471
  • 6
  • 52
  • 68
  • I've updated my question. I also have the same problem with **ABMultiValueRef emailInfo = ABRecordCopyValue(person, kABPersonEmailProperty);** – VansFannel Apr 14 '10 at 14:50