Retain and self with NSMutableArray - objective-c

In my .h file I have a NSMutableArray *locationsArray defined with a property as follows
#property (nonatomic, retain) NSMutableArray *locationsArray
In my .m file I was displaying a table view, this loaded fine until I tried to roll-up at which point I it crashed with bad access. This was due to the locationsArray not being retained.
This line of code fixed my problem in the .m
locationsArray = [[Locations loadLocations] retain] (#1)
This line of code also fixed the same problem
self.locationsArray = Locations.loadLocations (#2)
I have a couple of questions I need clarification on
is this the correct way to set this value, should I be doing an alloc init, alloc initwithArray?
Comming from a java world I understand self is this, or at least I thought I did...What is different in objective C that the locationsArray without the self is not being retained without me adding the retain.
Obviously I got it working but it took as while and am still a little confused as to why. any help would be appreciated.

Yes, if you set the instance variable (locationsArray) directly, you need to retain the value to keep it. You can either do that as you've done, or alloc/init it directly, which also means that you have a retain ownership of it.
self is indeed equivalent to this in other OO languages. But there's a semantic difference in Obj-C between referring to an ivar "naked" like in your first example, and referring to it as self.locationsArray in the second. The former behaves how you'd imagine, but the latter is actually a syntactic shortcut for [self setLocationsArray: ... ] which does the retain automatically for you, because you've marked the property as being retain.
This last point is really subtle, and (to my view) not expected or obvious behavior. If you're still fuzzy on it, go back to the Apple docs. Really important to get this.

Related

NSWindowController subclass will not release in ARC

I'm encountering a strange situation with NSWindowController. I want the window controller to be released but it will not. It doesn't seem to be following my expectations for ARC behavior.
I've created a simple window controller subclass, PlainWindowController. Its interface and implementation are empty:
#import <Cocoa/Cocoa.h>
#interface PlainWindowController : NSWindowController
#end
#implementation PlainWindowController
#end
I created with it a default windowController xib named PlainWindowController.xib, which has a window with delegate and windowController connections already set.
In a test, I've written this code:
PlainWindowController *strongWindowController = [[PlainWindowController alloc] initWithWindowNibName:#"PlainWindowController"];
__weak PlainWindowController *weakWindowController = strongWindowController;
[strongWindowController showWindow:nil];
strongWindowController = nil;
STAssertNil(weakWindowController, #"The window controller should have been deleted, wasn't");
When this test runs, the weak reference is not nil.
If I leave out the showWindow it is nil. If I use init instead of initWithWindowNibName, it is nil.
Does anyone know what's going on here? Thank you in advance for any guidance.
There’s no guarantee that an object under ARC hasn’t been added to the autorelease pool, in which case it won’t be freed until the end of the current event.
In your case, I strongly suspect somewhere within initWithWindowNibName: the controller gets retained and autoreleased.
If you really want to ensure your object is being freed, just subclass the -dealloc method and add an NSLog to it or break on it.
You generally shouldn't harbor "expectations" about when objects are deallocated if they've ever been passed to other code which you don't control.
Cocoa might have retained and then autoreleased the controller. Cocoa may retain the window controllers of any windows which are showing.
In general, when it comes to Cocoa memory management, you are supposed to make sure your own code follows the rules (which ARC largely does for you) and you should assume that other code follows the rules, but you can't assume that other code doesn't retain objects beyond where your interest ends. You should basically not care about what the other code is doing with respect to memory management.
If you really want to know what's happening, run your app under the Allocations instrument and explore the retain/release/autorelease history of your object after the point where you expected it to have been deallocated.
I had a similar issue when first using ARC. I unfortunately don't remember the details as this was more than a year ago. I eventually tracked it down as a circular retain problem using Instruments to monitor retain values, although not without losing a lot of hair.
I think the actual problem was with the delegate which I fixed with #property (unsafe_unretained) id delegate;
I ran into a similar issue yesterday with an ARC based project - a NSWindowController subclass would not deallocate, nor did -dealloc fire. I worked with Zombies, Allocations to no avail. The problem was very simple. There was a subclassed control within the window, and in that controls subclass .h header file a property was defined as:
#property id delegate;
correcting it to
#property (nonatomic, weak) id delegate;
fixed the issue.

Xcode/Cocoa: "object.property = value" sporadically failing? Can anyone explain this?

I'm writing a project where a very straightforward assignment is sporadically failing. Fascinated with this result and curious to see what y'all make of it.
I've got a project with a large data set, and I'm creating and display a modal window to present some details about a new class instance. So I've got a window with a custom window controller class, with the following code:
MyWindowController.h:
#import <DataModel.h>
#interface MyWindowController : NSWindowController
#property (nonatomic, weak) FooClass *fooInstance;
#end
MyWindowController.m:
#implementation MyWindowController
#synthesize fooInstance = _fooInstance;
-(void) init {
self = [super init];
if (self) {
self.fooInstance = [FooClass new];
}
return self;
}
#end
Totally cookie-cutter, right? But when I first added the form and ran it a bunch of times, the assignment failed over and over again. self.fooInstance kept coming back as nil. I even confirmed that the FooClass initializer was running (stepped right through it) and returning a non-null pointer to a valid FooClass instance. And yet, after the assignment line, self.fooInstance remained null.
I ran it a bunch of times, watching this same result over and over again. Then, I replaced just the assignment statement with this:
FooClass *foo = [FooClass new];
self.fooInstance = foo;
...and the assignment suddenly started working, and it's run consistently ever since. Even when I reverted the code back to self.fooInstance = [FooClass new], it's worked perfectly.
I couldn't believe it... until I saw it happen AGAIN, in the same project, while banging out the same type of window for a different class.
I don't understand what's happening. The self.fooInstance accessors are totally #synthesized; there is no code running in the background that might be futzing with the class (it's a single-threaded modal window); and there's nothing bound to the class. It just... doesn't work. It's like the code for the window classes doesn't run right until it's run a few times to break it in.
What in the world is happening? Does anyone even hazard a guess that might explain this behavior?
I recommend taking a read through Mike Ash's explanation of weak pointers. This section is the relevant bit:
Weak References
First, what is a weak reference? Simply put, a weak
reference is a reference (pointer, in Objective-C land) to an object
which does not participate in keeping that object alive. For example,
using memory management, this setter creates a weak reference to the
new object:
- (void)setFoo: (id)newFoo
{
_foo = newFoo;
}
Because the setter does not use retain, the reference does not keep the new object alive. It will stay alive as long as it's retained
by other references, of course. But once those go away, the object
will be deallocated even if _foo still points to it.
OK, that explains the first part, but why does the second part work?
Well, when you write an instance variable like:
FooClass *foo = //assignment
The compiler says to itself "it's a really good idea to keep this thing around, (at least til the function goes out of scope under ARC), and it turns it into this:
__strong FooClass *foo = //assignment
That means whatever I assigned is retained, and therefore, because at least one object owns it, I can assign it to my weak instance variable.

Is it ok to call release on a property in Objective C?

I've been teaching myself Objective C recently, and have noticed the following pattern used a lot in tutorials and sample code (including samples from the Apple site).
UIView *myUiView = [[UIView alloc] init];
self.uiView = myUiView;
[myUiView release];
I was just wondering though, it seems a bit of a waste to create a new variable, just to set a property. I've also seen the following pattern used too, but from what I understand its considered bad form to use autorelease on an iOS device as the autorelease pool takes up quite a bit of overhead which might not be good on a mobile device
self.uiView = [[[UIView alloc] init] autorelease];
I've been toying with using the following pattern recently, which sets the property, and then calls release on the property (to decrease the reference counter on the property itself).
self.uiView = [[UIView alloc] init];
[self.uiView release];
I've managed to use it on a few ViewControllers with no ill effects, but is this valid code, or am I missing something which makes it a bad idea?
The property getter is a method, and it does not have to return an ivar, it may actually get its return value anywhere, so you could release that, but it could be an autoreleased value already. If that is the case, you're in trouble.
IOW, if a property getter would do something like (not usual, but possible and valid):
- (NSString *) helloString
{
return [[myStringIVar copy] autorelease];
}
and you do:
[self.helloString release];
then you failed in two ways:
You did not release the ivar you wanted to release
You release an autoreleased object
IMO, it is better to release the ivar directly:
[myStringIVar release];
If the implementation of the property getter is simply to return the reference to the underlying ivar, then it is perfectly equivalent and you simply decrease the retain count of the allocated object.
On the other hand, if you can't be sure what the getter does (what if it returns something else than the ivar, e.g. some calculated result etc.), it may be dangerous.
No. It's not valid.
It will probably work on most retain properties but not necessarily. It will probably break on copy properties and assign properties.
Properties are just a pair of methods, one of which sets an abstract entity and one which gets it. There is absolutely no guarantee in general that the getter will give you the exact same object that you just passed to the setter. For instance, if you pass a mutable string to an NSString copy property, you definitely won't get back the same object.
Use either of the first two patterns. The first one does not waste anything. It is likely the local variable will only ever exist in a register. The overhead of the second will only last as long as the next autorelease pool drain and is only a few bytes (bear in mind that the actual object will last as long as self in any case).
It's not valid, and even in the cases where it does work its a bit "ugly" the other two are just to fix the property's retain characteristic from making the retain count 2 after having an alloc already making the retain count 1.
I tend to do what you described in the first example or the following.
in my #interface
#property (nonatomic, retain) UIView *uiView;
in my #implementation
#synthesize uiView = _uiView;
then when I setup the property.
_uiView = [[UIView alloc] init];
Thinking in terms of the reference counter, nothing is wrong with calling release using the property value. However, there are a few things, which I (personally) would dislike:
The property syntax is really just syntactic sugar for method calls. So, what your code really looks like, is
[self setUiView: [[UIView alloc] init]];
[[self uiView] release];
Another thing here might be more due to me thinking in strange ways, but I like to think of the reference counts as actually being related to references. A local variable holding a pointer to my object is such a reference. Having it present in the code reminds me, that I have something to do in order to clean things up properly (or, if not, at least write a short comment, why I don't have to clean up).
Directly going through the property forces me to think in terms of reference counts instead, which I don't like.

Cocoa ivar losing value between init and drawRect

I am not a complete n00b here, but I feel like I must be missing something essential. I'm passing a variable into a new class instance via the class's init method:
#synthesize side;
- (id)initWithSide:(NSString *)aSide frame:(NSRect)frameRect
{
if (self = [super initWithFrame:(NSRect)frameRect]) {
self.side = aSide;
}
NSLog(#"Side is %#", self.side);
return self;
}
The output from NSLog() does show the correct value here. Now, the drawRect: method that is then triggered to draw the view, has a similar call:
- (void)drawRect:(NSRect)rect
{
NSLog(#"Side is %#", self.side);
And this time the NSLog() reports Side as nil! Stepping through it with the debugger, I see the value for side gets set, then it goes into the registers (all those hex codes that I don't understand), then when it jumps out again into the drawRect: method, the value is simply nil.
If anyone can shed light on this I'd appreciate it!
Cheers,
Aaron
This is usually the way to write a property for NSString*.
assign is used for primitive types (it doesn't increment the retain count for an object), and either retain or copy for Objects.
#property (readwrite, copy) NSString * side
I'm going to go ahead and guess the most common cause for this kind of bug: You're dealing with two different objects. You're initializing the view in your code and you also have an instance in a nib. The two instances are completely separate objects, so when the view that is visible performs its drawRect:, it doesn't see the other one's instance variable.
The problem with your property that other people are pointing out is also definitely true, but I suspect this bug is actually hiding that one.

Do I need release in the dealloc?

In the book I'm studying from for iPhone dev, they utilize IBOutlet instances using the Interface Builder. An example would be a UIButton. So they add a thing in the struct like this:
IBOutlet UIButton *whateverButton;
Then they add a #property for each of these in the .h, and a #synthesize in the .m.
Then they include a release in the dealloc of the .m. Two questions:
Is the release necessary? Aren't all properties already handled automatically?
How can I check the ref count to see what's happening, for debug purposes...?
Is the release necessary? Aren't all
properties already handled
automatically?
If the property is retained, the release is necessary. When you declare a #property and #synthesize it, all you get is the accessors, there is no special automatic behaviour in dealloc.
Also, there is nothing magical about IBOutlet – it’s just a marker for Interface Builder to see which properties you would like to appear in IB. It’s simply an empty macro, Cmd-click the IBOutlet keyword to see its definition:
#ifndef IBOutlet
#define IBOutlet
#endif
Same thing goes for IBAction which expands to void.
How can I check the ref count to see
what's happening, for debug
purposes...?
When I need to debug memory management, I usually simply set up a breakpoint in the dealloc method or log a string there. It is also helpful to log the retainCount of an object around the calls that might do something fishy with it.
It might also help to see how the #synthesize directive creates the accessors. When you declare a retained #property and ask the compiler to #synthesize them, you get something like this:
#property(retain) NSString *foo;
#synthesize foo;
- (void) foo {
return foo;
}
- (void) setFoo: (NSString*) newFoo {
// Try to think what would happen if this condition wasn’t
// here and somebody called [anObject setFoo:anObject.foo].
if (newFoo == foo)
return;
[foo release];
foo = [newFoo retain];
}
This isn’t exactly the thing, but it’s close enough. Now it should be more clear why you should release in dealloc.
Properties are not "handled automatically." The closest that comes to being true is that synthesized accessors handle their memory management responsibilities properly. But that is just those accessors. Properties are just a way of declaring accessible "things" on your class. They don't get much special treatment beyond that. It doesn't turn on some sort of garbage collection. So yes, release is necessary.
And you should use the debugging tools like Instruments if you want to inspect a running app for leaks or memory that doesn't get released. I would not look at the ref count directly, because it's almost dangerously useless — there's no guarantee that the ref count will be what you expect at any point, and that doesn't necessarily indicate a problem.
You should read Apple's memory management rules for Cocoa. It's pretty simple once you've absorbed that. I wouldn't necessarily recommend reading other guides first, because subtle misstatements can lead you down the wrong path (for instance, the idea that properties will be released for you probably came from hearing somebody misstate how they work).
Is the release necessary? Aren't all
properties already handled
automatically?
It depends on how the property is implemented. If it is auto-implemented (#synthesize'd), the property will retain its value in the setter and release it if set to another value. If you just got into Obj-C and Cocoa, you should read about the conventions for memory management. I have put up a post on my blog about them, there are plenty of resources elsewhere too.
How can I check the ref count to see
what's happening, for debug
purposes...?
You can check the NSObject retainCount property. Information on that is here. For advanced debugging purposes, there is the NSZombieEnabled environment flag that will cause all release message to not decrement the reference count but log an error when an object that would have normally been released is accessed.