I want a property backed by a strong reference but which has a Core Foundation object type (not Objective-C object type) in ARC. I believe the proper way to do this was to mark it with __attribute__((NSObject))
and ARC will manage it just like an Objective-C object type property (i.e. release and retain on assign, and release when the containing object is dealloc
ed):
@interface Foo : NSObject
@property (nonatomic, strong) __attribute__((NSObject)) CFArrayRef bar;
@end
@implementation Foo
// property bar is auto-synthesized
@end
(I know CFArray
is toll-free bridged to NSArray
. This is just for the sake of an example. The real use case is for a Core Foundation type that does not have toll-free bridging.)
But when I put an object into the bar
property of a Foo
object and let the Foo
object go out of scope and get dealloc
ed, the object in bar
is leaked because it is not released when the Foo
object is deallocated, as it would with a regular Objective-C object type property:
void someFunc(void) {
Foo *foo = [[Foo alloc] init];
CFArrayRef arr = CFArrayCreateMutable(NULL, 42, &kCFTypeArrayCallBacks);
foo.bar = arr;
CFRelease(arr);
}
The code compiles without any warnings or errors, and passes Analyze with no issues. The Leaks instrument detects that the mutable array was leaked.
Is this a compiler bug? I am using the latest Xcode (8.3.3).
There is curious wording in the ARC specification, when defining retainable object pointer the last kind is defined as:
Note that this uses typdefs and not declarations. The phrasing is used again a little further in the spec. This almost seems to suggest you need to use a
typedef
for the attribute to be recognised, which would be a curious design.Unfortunately when it comes to property declarations the spec says (emphasis added):
This does appear to explain the behaviour you are seeing - the design is half-baked, the getter/setter adopt the semantics but deallocation doesn't.
Given the spec wording your one hope for automatic support seems to be to first create an attributed typedef for CF type and then use that in the property declaration... Weird if true, but it fits the curious wording... Sorry can't check this at the moment, but I'm guessing disappointment will be the outcome. Try assigning
nil
to the property in thedealloc
as that uses the setter which (according to the spec) has the correct semantics.HTH