Reputation: 5296
I have a non-ARC project that is using an ARC library. I am confused if I should release the object returned by the library method or not. Here is some example:
- (void)test{
LibObject* obj1 = [[LibObject alloc] init];
LibObject* obj2 = [obj1 otherObj];
[obj1 release]; //should I release it?
[obj2 release]; //should I release it?
}
Best to my knowledge, if the objects are in the autorelease pool, I should leave it alone. Otherwise, I should release it.
However, the ARC document says that
When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain while ensuring that the value lives across the call boundary. In the worst case, this may involve an autorelease, but callers must not assume that the value is actually in the autorelease pool.
Does the document imply that I should always release the object since I cannot assume the object is autoreleased?
Upvotes: 1
Views: 1791
Reputation: 540125
See Memory Management Policy in the "Advanced Memory Management Programming Guide":
You own any object you create
You create an object using a method whose name begins with “alloc”, “new”, “copy”, or “mutableCopy” (for example, alloc, newObject, or mutableCopy).You must not relinquish ownership of an object you do not own
These rules are consistent with methods compiled with ARC. In the ARC documentation, the behaviour of methods in the first category is described in "3.2.2. Retained return values":
When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, ...
which means that the caller must release the object.
Methods in the second category are described in "3.2.3. Unretained return values":
When returning from such a function or method, ARC retains the value at the point of evaluation of the return statement, then leaves all local scopes, and then balances out the retain ...
which means the the caller must not release the object.
So in your example:
LibObject* obj1 = [[LibObject alloc] init];
LibObject* obj2 = [obj1 otherObj];
[obj1 release]; //should I release it? --> YES
[obj2 release]; //should I release it? --> NO
You own obj1
, because it was created with alloc
, so you have to release obj1
.
You don't own obj2
, therefore you must not release it.
Note: If you run the Xcode static analyzer on your code, it shows exactly where these rules are violated.
Upvotes: 4
Reputation: 3090
With my understanding is that in your non-ARC code, you just do all the retain / release with ARC-enabled library as always (just like interacting with other non-ARC code).
I have created a simple app to prove this behaviour.
Testing Code - compiled without ARC
- (void)testARC
{
ARCLib *al = [[ARCLib alloc] init];
NSLog(@"%p retainCount = %u", al, [al retainCount]);
[al release];
ARCLib *al2 = [ARCLib arcLib];
NSLog(@"%p retainCount = %u", al2, [al2 retainCount]);
}
ARCLib - compiled with ARC
@implementation ARCLib
+ (id)arcLib
{
return [[self alloc] init];
}
- (id)init
{
self = [super init];
if (self)
{
NSLog(@"%p init",self);
}
return self;
}
- (void)dealloc
{
NSLog(@"%p dealloc",self);
}
@end
Result
2012-12-13 20:15:21.879 ARCTest[15206:907] 0x1e821500 init
2012-12-13 20:15:21.883 ARCTest[15206:907] 0x1e821500 retainCount = 1
2012-12-13 20:15:21.884 ARCTest[15206:907] 0x1e821500 dealloc
2012-12-13 20:15:21.885 ARCTest[15206:907] 0x1dd26060 init
2012-12-13 20:15:21.886 ARCTest[15206:907] 0x1dd26060 retainCount = 1
2012-12-13 20:15:21.893 ARCTest[15206:907] 0x1dd26060 dealloc
Answer to your question
You should release your obj1, but don't need to release obj2.
Upvotes: 0
Reputation: 107231
When you get an object from ARC enabled class to your non-ARC enabled class you have the responsibility to manage the memory.
ARC just simply put retain, release in your ARC enabled code during compile time. It won't manage the memory on other classes or objects that is in non-ARC mode.
You should release such objects after your need.
Upvotes: 2
Reputation: 1705
My understanding is that if you use the compiler flag -fno-objc-arc
for this file you need to take care of retain/release yourself. So you should call [obj1 release]
. If you weren't supposed to call it yourself, the compiler would warn you accordingly.
Upvotes: 0