ARC doesn't work properly in Xcode with Objective-C - objective-c

I have a dilemma with strong and weak references in Xcode with Obj-C.
When I create two objects with cross-references to each other inside, all weak:
Mouse *mouse = [[Mouse alloc] initWithComputer:nil];
Computer *computer = [[Computer alloc] initWithMouse:mouse];
NSLog(#"%#", computer.mouse); //prints legit address
mouse = nil; //destroy the ONLY strong reference to Mouse
NSLog(#"%#", computer.mouse); //still prints(holds) the same legit address
Before mouse = nil;
After mouse = nil;
After "destroying" the ONLY strong reference to Mouse class mouse, an instance of Mouse computer.mouse still holds the same memory address when it should be deallocated.
Absolutely the same code only in SWIFT in Xcode works correctly and deallocates the memory being held by computer.mouse making it nil
Is anything wrong with my Obj-c code? My Xcode is up to date, though with the previous version I had no luck either in Obj-c. I would appreciate any help.
Here are my classes:
Computer.h
#import <Foundation/Foundation.h>
#class Mouse;
#interface Computer : NSObject
#property (nonatomic, weak) Mouse *mouse;
- (instancetype) initWithMouse: (Mouse *) userPutMouse ;
#end
Computer.m
#import "Computer.h"
#import "Mouse.h"
#implementation Computer
- (instancetype) initWithMouse: (Mouse *) userPutMouse {
self = [super init];
if (self) {
self.mouse = userPutMouse;
self.mouse.computer = self;
}
return self;
}
#end
Mouse.h
#import <Foundation/Foundation.h>
#class Computer;
#interface Mouse : NSObject
#property (nonatomic, weak) Computer *computer;
- (instancetype) initWithComputer: (Computer *) userPutComputer;
#end
Mouse.m
#import "Mouse.h"
#import "Computer.h"
#implementation Mouse
- (instancetype) initWithComputer: (Computer *) userPutComputer {
self = [super init];
if (self ) {
if (userPutComputer) {
self.computer = userPutComputer;
}
}
return self;
}
#end

Your getters, being automatically synthesised, are placing the objects they return into the autorelease pool. Therefore your assignment of mouse to nil does not end the final owning reference. Never assume you are the only person with owning references to anything, only ensure that you follow appropriate behaviour.
For empirical demonstration, try this:
Mouse *mouse;
Computer *computer;
#autoreleasepool {
mouse = [[Mouse alloc] initWithComputer:nil];
computer = [[Computer alloc] initWithMouse:mouse];
NSLog(#"%#", computer.mouse); //prints legit address
mouse = nil; //destroy **my** ONLY strong reference to Mouse
}
NSLog(#"%#", computer.mouse); //prints (null)
... but also never try to diagnose whether proper ownership is happening empirically. That's why the retainCount property is no longer available.
EDIT: to expand: the traditional behaviour expected of a getter is to return a non-owning reference that is nevertheless guaranteed to live for at least as long as the current call stack. This is so that, in pre-ARC days, you could use getters directly for supplying properties as arguments (in which case, don't burden the caller with memory management) or for getting something the caller can hold on to transiently, even if the original owner is deallocated in the meantime (i.e. the classic autorelease pool usage of making things act a bit like they're just on the stack). And then ARC just implements the old-fashioned rules but automatically, for full interoperability.

Related

debugging objective c memory leak with xCode Leaks

I'm doing my first steps in finding memory leaks in xCode 4.5 and using the Leaks instrument. I found a couple of issues and seemed to fix them, but this one eludes me.
Here is the code:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo->name = nm;
[imgInfo->name retain]; // I'm using it outside of this method
Leaks reports a leak in the second line, with the percentage next to the "i" at %100.
So I tried two things:
One, I marked nm with autohrleas like this:
NSString *nm = [[NSString stringWithUTF8String:img->name.c_str()] autorelease];
Two, I also tried calling release on nm after it's assignment to imgInfo->name so the code looks like this:
imgInfo->name = nm;
[imgInfo->name retain];
[nm release];
But in both cases the app crashes with BAD_ACCESS when I run it, and call [imgInfo->name UTF8String].
What am I missing?
EDIT following Rob's answer:
This is the RUBEImageInfo class:
#import "cocos2d.h"
#interface RUBEImageInfo : NSObject {
#public CCSprite* sprite; // the image
#public NSString* name; // the file the image was loaded from
#public class b2Body* body; // the body this image is attached to (can be NULL)
#public float scale; // a scale of 1 means the image is 1 physics unit high
#public float angle; // 'local angle' - relative to the angle of the body
#public CGPoint center; // 'local center' - relative to the position of the body
#public float opacity; // 0 - 1
#public bool flip; // horizontal flip
#public int colorTint[4]; // 0 - 255 RGBA values
}
#end
And the .m:
#import "RUBEImageInfo.h"
#implementation RUBEImageInfo
// Nothing much to see here. Just make sure the body starts as NULL.
-(id)init
{
if( (self=[super init])) {
body = NULL;
}
return self;
}
-(void) dealloc {
[name release];
[super dealloc];
}
#end
A couple of reactions:
Instruments identified where the leaked object was allocated, but in this case, this code might not be the source of the leak. You should:
ensure you release the name in the dealloc method of RUBEImageInfo; and
also, if you're setting name a second time, make sure you release the previous name object before you set it to a new object.
Your life will be much easier if you use declared properties rather than dereferencing class instance variables. For example, if name was declared as:
#property (nonatomic, copy) NSString *name; // you could use `retain`, too, but `copy` is safer when dealing with strings
Then you would set the name property as so:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo.name = nm;
// this is no longer needed as the `name` setter will take care of memory semantics
// [imgInfo->name retain]; // I'm using it outside of this method
By using the setter accessor method (i.e. the "dot syntax" of imgInfo.name), it will take care of a lot of routine memory semantics of releasing any previous object that name may have referenced, and it will do the necessary copy or retain. Obviously, the RUBEImageInfo method dealloc still needs to release name, but at least it simplifies the memory semantics of the name property of RUBEImageInfo objects.
Since you are using manual reference counting, I'd encourage you to investigate the "static analyzer" (invoked by selecting "Analyze" from Xcode's "Product" menu). The Leaks tool in Instruments will tell you what leaked, but it doesn't tell you where the leak happened; it has no way of knowing; it can only show you where the leaked object was allocated and you'll have to hunt down the logic error yourself. The static analyzer can sometimes point out errors that lead to leaks, but more importantly, show you where the leak was caused, rather than just where the leaked object was originally instantiated. You should have a clean bill of health from the static analyzer before you even bother running Instruments.
Looking at your code sample, if you're not going to use declared properties (not sure why you wouldn't, as it makes life easier, but to each his own), I'd suggest making sure you initialize all of your objects in init and release all of them in dealloc:
#implementation RUBEImageInfo
-(id)init
{
if ((self=[super init])) {
body = NULL;
name = nil;
sprite = nil;
// I might initialize other class instance variables here, too, but that's up to you
}
return self;
}
-(void) dealloc {
[name release];
// shouldn't you release `body` and `sprite`, too?
[super dealloc];
}
#end
Then your code that sets the name instance variable would make sure to release the previous object before setting the new object. Thus the initial instantiation might look like:
RUBEImageInfo* imgInfo = [[[RUBEImageInfo alloc] init] autorelease];
NSString *nm = [NSString stringWithUTF8String:img->name.c_str()];
imgInfo->name = [nm retain]; // retain the new object
But if you update it later, you should:
NSString *nm = [NSString stringWithUTF8String:someNewImg->name.c_str()];
[imageInfo->name release]; // release the old one
imgInfo->name = [nm retain]; // retain the new object

How to retain my own objects and properties

I'm not sure I understood how alloc and retain work.
Recently I discovered that the NSString properties were not retained and I had to add [myString copy] when I set them. Which makes me wonder if I misunderstood the whole way of using retain/alloc
Please, may someone tell me if I'm doing it correctly? I read a lot and had a look on open source projects, this let me thing that I may have been wrong since the beginning.
Here is my way of doing it:
/**** VIEW.h *****/
#import "MyClass.h"
#interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
#property (nonatomic, retain) MyClass *myObject;
- (void)defineObject;
#end
.
/**** VIEW.m *****/
#import "VIEW.h"
#implementation MyViewController
#dynamic myObject;
- (void)viewDidLoad
{
[super viewDidLoad];
[self defineObject];
NSLog(#"My object's name is: %#", myObject.name);
}
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "#property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:#"my name"];
}
.
/**** MyClass.h *****/
#interface MyClass : NSObject {
//not sure if this line is still necessary
NSString *name;
}
#property (nonatomic, retain) NSString *name;
- (id)initPersonalised;
- (void)setName:(NSString *)name;
- (NSString *)name;
#end
.
/**** MyClass.m *****/
#import "MyClass.h"
#implementation MyClass
#dynamic name;
(id)initPersonalised{
self = [super init];
name = #"Undefined";
}
- (void)setName:(NSString *)name{
self.name = [name copy];
}
- (NSString *)name{
return [self.name copy];
}
#end
I hope you can bring a bit of light, after months of programming this way, I'm less and less sure of doing it well.
This is indeed a topic that every Objective C programmer stumbles upon. There are a few things one needs to know:
Instance variable vs. property access
Within MyViewController,
myObject = xxx;
and
self.myObject = xxx;
are two different things. The first directly assigns to the instance variable and does neither release to old referenced insance nor retain the newly assigned instance. The latter one uses the property setter and thus releases the old and retains the new value.
Deallocation
Even when you have declared an implemented a property that takes care of retaining and releases the values, it won't take care of deallocation when your object (MyViewController in your case) is released. So you must explicitly release it in dealloc:
-(void) dealloc {
[myObject release];
[super dealloc];
}
Now to your code:
The snippet:
myObject = [[MyClass alloc] initPersonalised];
is perfectly okay. When you create an object, you use the pair of alloc and initXXX. The always create an instance with the reference count set to 1. So by directly assigning it to the instance variable, you create a clean constellation. I don't see no other way of creating the instance.
In MyClass you could use #synthesize name instead of #dynamic. Then the compiler would implement name and setName: automatically and you wouldn't need to do it yourself.
Finally, your missing dealloc.
Update:
If you use:
self.myObject = [[MyClass alloc] initPersonalised];
then you have a memory leak because initPesonalised sets the reference count to 1 and the setter of myObject increases it to two. If you want to use the setter, then I has to be:
MyClass* mo = [[MyClass alloc] initPersonalised];
self.myObject = [[MyClass alloc] initPersonalised];
[mo release];
It would be different if you weren't using initXXX to create a new instance. The class NSString for example has many methods called stringXXX, which create a new instance (or return a shared one) that has (conceptually) a reference count of 1 that will later automatically decreased by one. Then you better use the setter:
self.name = [NSString stringWithFormat: #"instance %d", cnt];
If you want to use copy instead of retain for your string property (which is good practice), then you can simply declare your property like this:
#property (nonatomic, copy) NSString *name;
When you then use #synthesize to implement the getter and setter, the compiler will generate them using copy instead of retain.
And NSString *name; is necessary even if you use #property and/or #synthesize to implement the property.
Alloc and init are methods that always go hand-in-hand. alloc allocates space for your object, and init initializes your object to some value. When you call alloc, you are responsible for freeing that object later. If you call copy, you are also responsible for releasing that object later. It's considered good practice to always initialize your objects right after you allocate them.
Now, to answer the questions I found in your code.
#interface MyViewController : UIViewController {
//Is the following line really necessary?
MyClass *myObject;
}
So is that line necessary? That depends. Does it make sense that your object has a MyClass as a property? This is a question only you can answer based on your design. I recommend you to study Object-Oriented Programming in more depth.
- (void)defineObject
{
//Here particularly, Why doesn't it work without both alloc and init
//shouldn't "#property (nonatomic, retain) MyClass *myObject;" have done that already?
myObject = [[MyClass alloc] initPersonalised];
[myObject setName:#"my name"];
}
Not necessarily. You are just providing a pointer to an object of the specified kind. The moment you set your property, depending on the property modifiers, your class will know what to do with MyObject.
In that way, there's no need to call [yourObject copy]. In this way your properties will be copied instead of being retained. Just don't forget to release it later in your -dealloc method, like you would with retain properties.
All in all, this is what I recommend you to study a bit more:
Object-Oriented Programming (not related to your issue, but I can tell you are not comfortable using it. Objective-C is heavily object oriented, so you want to understand OOP).
iOS Memory Management.
You can have a look at the Memory Management Guide. It will help you to better understand the alloc & retain concepts; hope this helps you.

How to Make a Basic Finite State Machine in Objective-C

I am attempting to build an FSM to control a timer in (iphone sdk) objective c. I felt it was a necessary step, because I was otherwise ending up with nasty spaghetti code containing pages of if-then statements. The complexity, non-readability, and difficulty of adding/changing features lead me to attempt a more formal solution like this.
In the context of the application, the state of the timer determines some complex interactions with NSManagedObjects, Core Data, and so forth. I have left all that functionality out for now, in an attempt to get a clear view of the FSM code.
The trouble is, I cannot find any examples of this sort of code in Obj-C, and I am not so confident about how I have translated it from the C++ example code I was using. (I don't know C++ at all, so there is some guessing involved.) I am basing this version of a state pattern design on this article: http://www.ai-junkie.com/architecture/state_driven/tut_state1.html. I'm not making a game, but this article outlines concepts that work for what I'm doing.
In order to create the code (posted below), I had to learn a lot of new concepts, including obj-c protocols, and so forth. Because these are new to me, as is the state design pattern, I'm hoping for some feedback about this implementation. Is this how you work with protocol objects effectively in obj-c?
Here is the protocol:
#class Timer;
#protocol TimerState
-(void) enterTimerState:(Timer*)timer;
-(void) executeTimerState:(Timer*)timer;
-(void) exitTimerState:(Timer*)timer;
#end
Here is the Timer object (in its most stripped down form) header file:
#interface Timer : NSObject
{
id<TimerState> currentTimerState;
NSTimer *secondTimer;
id <TimerViewDelegate> viewDelegate;
id<TimerState> setupState;
id<TimerState> runState;
id<TimerState> pauseState;
id<TimerState> resumeState;
id<TimerState> finishState;
}
#property (nonatomic, retain) id<TimerState> currentTimerState;
#property (nonatomic, retain) NSTimer *secondTimer;
#property (assign) id <TimerViewDelegate> viewDelegate;
#property (nonatomic, retain) id<TimerState> setupState;
#property (nonatomic, retain) id<TimerState> runState;
#property (nonatomic, retain) id<TimerState> pauseState;
#property (nonatomic, retain) id<TimerState> resumeState;
#property (nonatomic, retain) id<TimerState> finishState;
-(void)stopTimer;
-(void)changeState:(id<TimerState>) timerState;
-(void)executeState:(id<TimerState>) timerState;
-(void) setupTimer:(id<TimerState>) timerState;
And the Timer Object implementation:
#import "Timer.h"
#import "TimerState.h"
#import "Setup_TS.h"
#import "Run_TS.h"
#import "Pause_TS.h"
#import "Resume_TS.h"
#import "Finish_TS.h"
#implementation Timer
#synthesize currentTimerState;
#synthesize viewDelegate;
#synthesize secondTimer;
#synthesize setupState, runState, pauseState, resumeState, finishState;
-(id)init
{
if (self = [super init])
{
id<TimerState> s = [[Setup_TS alloc] init];
self.setupState = s;
//[s release];
id<TimerState> r = [[Run_TS alloc] init];
self.runState = r;
//[r release];
id<TimerState> p = [[Pause_TS alloc] init];
self.pauseState = p;
//[p release];
id<TimerState> rs = [[Resume_TS alloc] init];
self.resumeState = rs;
//[rs release];
id<TimerState> f = [[Finish_TS alloc] init];
self.finishState = f;
//[f release];
}
return self;
}
-(void)changeState:(id<TimerState>) newState{
if (newState != nil)
{
[self.currentTimerState exitTimerState:self];
self.currentTimerState = newState;
[self.currentTimerState enterTimerState:self];
[self executeState:self.currentTimerState];
}
}
-(void)executeState:(id<TimerState>) timerState
{
[self.currentTimerState executeTimerState:self];
}
-(void) setupTimer:(id<TimerState>) timerState
{
if ([timerState isKindOfClass:[Run_TS class]])
{
secondTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(currentTime) userInfo:nil repeats:YES];
}
else if ([timerState isKindOfClass:[Resume_TS class]])
{
secondTimer = [NSTimer scheduledTimerWithTimeInterval:1.0 target:self selector:#selector(currentTime) userInfo:nil repeats:YES];
}
}
-(void) stopTimer
{
[secondTimer invalidate];
}
-(void)currentTime
{
//This is just to see it working. Not formatted properly or anything.
NSString *text = [NSString stringWithFormat:#"%#", [NSDate date]];
if (self.viewDelegate != NULL && [self.viewDelegate respondsToSelector:#selector(updateLabel:)])
{
[self.viewDelegate updateLabel:text];
}
}
//TODO: releases here
- (void)dealloc
{
[super dealloc];
}
#end
Don't worry that there are missing things in this class. It doesn't do anything interesting yet. I'm currently just struggling with getting the syntax correct. Currently it compiles (and works) but the isKindOfClass method calls cause compiler warnings (method is not found in protocol). I'm not really sure that I want to use isKindOfClass anyway. I was thinking of giving each id<TimerState> object a name string and using that instead.
On another note: all those id<TimerState> declarations were originally TimerState * declarations. It seemed to make sense to retain them as properties. Not sure if it makes sense with id<TimerState>'s.
Here is an example of one of the state classes:
#import "TimerState.h"
#interface Setup_TS : NSObject <TimerState>{
}
#end
#import "Setup_TS.h"
#import "Timer.h"
#implementation Setup_TS
-(void) enterTimerState:(Timer*)timer{
NSLog(#"SETUP: entering state");
}
-(void) executeTimerState:(Timer*)timer{
NSLog(#"SETUP: executing state");
}
-(void) exitTimerState:(Timer*)timer{
NSLog(#"SETUP: exiting state");
}
#end
Again, so far it doesn't do anything except announce that what phase (or sub-state) it's in. But that's not the point.
What I'm hoping to learn here is whether this architecture is composed correctly in the obj-c language. One specific problem I'm encountering is the creation of the id objects in the timer's init function. As you can see, I commented out the releases, because they were causing a "release not found in protocol" warning. I wasn't sure how to handle that.
What I don't need is comments about this code being overkill or meaningless formalism, or whatever. It's worth me learning this even it those ideas are true. If it helps, think of it as a theoretical design for an FSM in obj-c.
Thank you in advance for any helpful comments.
(this didn't help too much: Finite State Machine in Objective-C)
I suggest using State Machine Compiler, it will output Objective-C code. I have had good success in Java and Python using this.
You shouldn't be writing state machine code by hand, you should be using something to generate the code for you. SMC will generate clean clear code you can then look at if you want to learn from it, or you can just use it and be done with it.
When you use a protocol as a type-modifier, you can provide a comma-separated list of protocols. So all you need to do to get rid of the compiler warning is add NSObject to the protocol list like so:
- (void)setupTimer:(id<TimerState,NSObject>) timerState {
// Create scheduled timers, etc...
}
If you want a very simple, Objective-C implementation of a State Machine I've just released TransitionKit, which provides a well designed API for implementing state machines. It's thoroughly tested, well documented, very easy to use, and doesn't require any code generation or external tools.
I'd suggest checking out Statec it's got a nice little dsl for doing FSM and outputs ObjC code. It's sort of like mogenerator for state machines.
I am rather new at Objective-C, but I would suggest that you look at straight ANSI C implementation for the State Machine.
Just because you're using Cocoa doesn't mean you have to use Objective-C messages here.
In ANSI C, a state machine implementation can be very straightforward and readable.
My last implementation in C of a FSM specified #define STATE_x or enumerate types for the states and had a table of pointers to functions to execute each state.

How is release handled for #synthesized retain properties?

I have some questions about synthesized properties in Objective-C. The full list follows, but the basic question is this: How does the compiler ensure that the ivars for synthesized properties are properly released, even though my code may or may not include release methods in dealloc?
Note: I decided not to post these as individual questions because they are so closely related and because there are a handful of existing questions that touch on the individual issues without really getting to the heart of the matter.
Somewhat similar questions:
Does property retain need a release?
What's the difference between property and synthesize?
Question on retain attribute with property and synthesize
Setup: Consider a class with a single property:
#interface Person : NSObject
{
NSString * name;
}
#property (nonatomic, retain) name;
#end
Question #1: The very basic case:
#implementation Person
#synthesize name;
#end
With this setup, I assume that name will be automatically released whenever a Person object is released. In my mind, the compiler simply inserts [name release] into the dealloc method as if I had typed it myself. Is that correct?
Question #2: If I choose to write my own dealloc method for this class, and I omit a call to [name release], will that leak?
#implementation Person
#synthesize name;
- (void)dealloc { [super dealloc]; }
#end
Question #3: If I choose to write my own dealloc method for this class, and I include a call to [name release], will that result in a double-release, since #synthesize has already taken care of it for me?
#implementation Person
#synthesize name;
- (void)dealloc { [name release]; [super dealloc]; }
#end
Question #4: If I choose to write my own property accessor for this class, but I do not write my own dealloc method, will name be leaked?
#implementation Person
#dynamic name;
- (void)setName:(NSString *)newName
{
[newName retain];
[name release];
name = newName;
}
#end
Question #5: I have a feeling (based on experience) that none of the above scenarios will result in leaks or double-releases, since the language has been designed to avoid them. That, of course, raises the question of "how?". Is the compiler simply smart enough to keep track of every possible case? What if I were to do the following (note that this is a ludicrous example, just meant to illustrate my point):
void Cleanup(id object) { [object release]; }
#implementation Person
#synthesize name;
- (void)dealloc { Cleanup(name); }
#end
Would that fool the compiler into adding another [name release] to the dealloc method?
Q1:
No. #synthesize does not modify the -dealloc for you. You have to -release the name yourself.
Q2:
Yes it will leak. Same reason as Q1.
Q3:
No it won't double-release. Same reason as Q1.
Q4:
Yes it will leak. Same reason as Q1.
Q5:
No it won't double-release. Same reason as Q1.
You can check this yourself by overriding -retain and -release and -dealloc to report what is going on.
#import <Foundation/Foundation.h>
#interface X : NSObject {}
#end
#implementation X
-(oneway void)release {
NSLog(#"Releasing %p, next count = %d", self, [self retainCount]-1);
[super release];
}
-(id)retain {
NSLog(#"Retaining %p, next count = %d", self, [self retainCount]+1);
return [super retain];
}
-(void)dealloc {
NSLog(#"Dealloc %p", self);
[super dealloc];
}
#end
#interface Y : NSObject {
X* x;
}
#property (nonatomic, retain) X* x;
#end
#implementation Y
#synthesize x;
- (void)dealloc { [x release]; [super dealloc]; }
#end
int main () {
NSAutoreleasePool* pool = [[NSAutoreleasePool alloc] init];
Y* y = [[Y alloc] init];
X* x = [[X alloc] init];
y.x = x;
[y release];
[x release];
[pool drain];
return 0;
}
In Q1, Q2 and Q4, the last -retainCount of x is 1, so there is a leak, and in Q3 and Q5 the last -retainCount is 0 and -dealloc is called, so there is no leak.
From the Objective-C documentation on properties:
dealloc
Declared properties fundamentally take
the place of accessor method
declarations; when you synthesize a
property, the compiler only creates
any absent accessor methods. There is
no direct interaction with the dealloc
method—properties are not
automatically released for you.
Declared properties do, however,
provide a useful way to cross-check
the implementation of your dealloc
method: you can look for all the
property declarations in your header
file and make sure that object
properties not marked assign are
released, and those marked assign are
not released.
This essentially answers all your questions.
The simple and general rule: if you allocate, retain, or copy an object, YOU have to release it.
When you use the retain setter semantic setting in a #synthesize statement, you're asking the compiler to build for you a setter that calls retain on the object. Nothing more, nothing less. And since you are retaining that object (even though it's via magically auto-generated code), you have to release it, and where to release it is in -(void)dealloc.
Something else it's worth knowing - if you have a synthesised property, setting that property to nil (using dot syntax, of course) will release the ivar for you.

I have a circular reference. How can I create a weak reference in Objective-C?

I'm working on an iPhone application. I have an object of class Row that needs to release numerous objects of the class Block. Every Block currently has a property that retains an instance variable of class Row.
#interface Block : UIImageView {
Row *yCoord;
}
#property (nonatomic,retain) Row *yCoord;
#end
Every Row contains an NSMutableArray of these Blocks.
#interface Row : NSObject {
NSMutableArray *blocks;
}
-(void)addBlock:(Block*)aBlock;
#end
#implementation Row
-(void)addBlock:(Block*)aBlock {
[blocks addObject:aBlock];
aBlock.yCoord = self;
}
#end
I understand that this is a circular reference. Apple's documentation states that in order to deallocate an object with a circular reference I need a weak reference instead of a strong reference (a retain property), but it doesn't follow through and explain how exactly I go about doing so. I plan to release and dealloc all Blocks within a Row as well as the Row itself simultaneously. How do I set up a weak reference within each of my Blocks to their "parent" Row?
Edit: Since the asker clarified he's not using garbage collection (iPhone currently does not support it), my advice is to avoid cycles by having only one of the objects retain the other, just as you would do with a delegate. When using properties, use "assign" instead of "retain" to achieve this. For example:
#property (nonatomic,assign) Row *yCoord;
The rest of my answer answer relates to "weak references" in terms of Objective-C 2.0 and GC.
When you're working with garbage collection (10.5+), a weak reference is created by prefixing a variable declaration with __weak. When you assign to that variable, the GC (if enabled) keeps track of the reference and will zero it out for you automatically if all strong references to the referenced object disappear. (If GC is not enabled, the __weak attribute is ignored.)
Thus, you can safely modify the above answer to play nicer with garbage collection (currently on 10.5+, and perhaps someday on iPhone) as follows: (See the related Apple docs.)
#property (nonatomic,assign) __weak Row *yCoord;
To quote Chris Hanson (where you can find more detailed information):
"By prefixing an instance variable declaration with __weak, you tell the garbage collector that if it's the only reference to an object that the object should be considered collectable."
I'd clarify that by saying "if there are no non-weak references to an object". As soon as the last strong reference is removed, the object may be collected, and all weak references will be zeroed automatically.
Note: This isn't directly related to creating weak references, but there is also a __strong attribute, but since Objective-C object variables are strong references by default, it is generally used only for raw C pointers to things like structs or primitives that the Garbage Collector will not treat as roots, and will be collected from under you if you don't declare them as strong. (Whereas the lack of __weak can cause retain cycles and memory leaks, the lack of __strong can result in memory stomping and really strange and insidious bugs that occur non-deterministically and can be quite difficult to track down.)
Just change it to assign instead of retain, no more circular references.
#interface Block : UIImageView {
Row *yCoord;
}
#property (nonatomic,assign) Row *yCoord;
#end
A weak reference is simply an assignment (unless you're talking about Garbage Collection which is a whole separate can of worms, but does not suffer from retain cycles).
Normally, in Cocoa, Row would retain the Block objects (by including them in the NSMutableArray), but Block would not retain Row, each would simply store it in an ivar (with an "assign" property).
As long as Row is careful to release each Block before it is deallocated (ie, its dealloc should release the NSMutableArray which will release the Blocks as long as no one else has any pointers to them) then everything will be deallocated as appropriate.
You can also take the precaution of zeroing the row reference from Blocks before removing the entiries from the array, something like:
- (void) dealloc {
for (Block* b in _blocks) {
b.row = nil;
}
[_blocks release];
[super dealloc];
}
where _blocks is the ivar referenced by the blocks property.
Using assign to create weak references can be unsafe in a multithreaded system, particularly when either object can be retained by a third object, and then used to dereference the other object.
Fortunately, this is often a problem of hierarchy, and the object containing the weak reference only cares about the object it refers to for the referred-to object's lifetime. This is the usual situation with a Superior<->Subordinate relationship.
I think that the case in the OP's comment maps to this, with Row = Superior, Block = Subordinate.
In this case, I would use a handle to refer to the Superior from the Subordinate:
// Superior.h
#class Superior;
#interface SuperiorHandle : NSObject {
#private
Superior* superior_;
}
// note the deliberate avoidance of "nonatomic"
#property (readonly) Superior *superior;
#end
#interface Superior : NSObject {
#private
SuperiorHandle *handle_;
// add one or more references to Subordinate instances
}
// note the deliberate avoidance of "nonatomic"
#property (readonly) SuperiorHandle *handle;
#end
// Superior.m
#import "Superior.h"
#implementation SuperiorHandle
#synthesize
superior = superior_;
- (id)initWithSuperior:(Superior *)superior {
if ((self = [super init])) {
superior_ = superior; // weak reference
}
}
- (void)invalidate {
#synchronized (self) {
superior_ = nil;
}
}
- (Superior *)superior {
#synchronized (self) {
// retain and autorelease is required to prevent dealloc before we're ready, thanks to AndroidDev for pointing out this mistake
return [[superior_ retain] autorelease];
}
}
#end
#implementation Superior
#synthesize
handle = handle_;
- (id)init {
if ((self = [super init])) {
handle_ = [[SuperiorHandle alloc] initWithSuperior:self];
}
return self;
}
- (void)dealloc {
[handle_ invalidate];
[handle_ release];
[super dealloc];
}
#end
// Subordinate.h
#class Superior;
#class SuperiorHandle;
#interface Subordinate : NSObject {
#private
SuperiorHandle *superior_handle_;
}
#property (readonly) Superior *superior;
#end
// Subordinate.m
#import "Subordinate.h"
#import "Superior.h"
#implementation Subordinate
// no synthesize this time, superior's implementation is special
- (id)initWithSuperior:(Superior *)superior {
if ((self = [super init])) {
superior_handle_ = [superior.handle retain];
}
return self;
}
- (void)dealloc {
[superior_handle_ release];
[super dealloc];
}
- (Superior *)superior {
#synchronized (superior_handle_) {
return superior_handle_.superior;
}
}
#end
Some advantages:
It's thread safe. There is no way you can have the weak reference contained in Subordinate become an invalid pointer. It may become nil but that is OK.
Only the objects themselves need to know about the embedded weak reference. All other objects can treat Subordinate as if it has a regular reference to Superior.