Objective C - Memory management question? - objective-c

I know that when i have a property for an object which is set to retain or copy i must do the following.
Object *o = [[Object alloc] init];
self.myObject = o;
[o release];
but what if i don't define a property for myObject?
Can i do the following without having a leak?
Is it better to define a property for every variable I have in every class? Why??
myObject = [[Object alloc] init];

Yes, you can set an instance variable that way and it's totally fine — in fact, that's the preferred way to do it in init methods (because setters might have side effects). Just remember to release the old object (if any) in the variable before setting a new one or you'll leak. And whether you use properties or set the ivar directly, you need to release the object in dealloc.

What you can do is ensure you release the previously allocated object before assigning the variable holding it to a new instance (be it a retained version of another object, or a copy of it).
If you don't define a property for it, don't use the dot syntax.

Because Jacob already answered the part of without property. I will answer the left
Can i do the following without having a leak?
myObject = [[Object alloc] init];
You have to release the myObject somewhere, maybe in the delegate method, or maybe after you finish using it, but remember to release the object, especially before you lose the object reference
Is it better to define a property for every variable I have in every class? Why??
It depends on your coding convention, define all properties will help you with memory management a lot, but it comes with burden and sometimes your team doesn't want to define instance variable, property and synthesize for every variable, which means quite a lot of codes. So, discussing with your team to see what is your weakness and strength. If you are weak at memory management, I recommend to define for every

You don't need to have any properties. Obj-C didn't even have them at all until a couple of years ago with Obj-C 2. Properties are a convenience - they give you some memory management without you writing boilerplate code (the access methods are synthesized for you), and you can use dot notation, which some people are more familiar with than the usual Obj-C syntax.
Having said that properties take care of memory management for you, that's only partially true. You still need to set all properties to nil in your dealloc method. So that really doesn't buy you much, since without properties you'd still need to release each object in dealloc.
The big benefit is that properties handle reference counting for you when assigning objects from one place to another. You don't have to write the getters and setters manually. For this reason, I like properties. Plus, clang is gaining the ability to have properties where you only need the #property line, no need for a backing variable, and no need for an #synthesize line. One-line properties are a win in my book. (OK, two lines, you need to add a line to dealloc too :)

Related

Conflict between memory management descriptions in ObjC book and official docs

I'm trying to learn/understand what happens and why when working with or creating various objects. (Hopefully to LEARN from the docs.)
I'm reading "Programming in Objective-C 2.0" (2nd edition, by Steven Kochan). On page 408, in the first paragraph is a discussion of retain counts:
Note that its reference count then goes to 2. The addObject: method does this automatically; if you check your documentation for the addObject: method, you will see this fact described there.
So I read the addObject: docs:
Inserts a given object at the end of the array.
There, the description is missing, while other items, like arrayByAddingObject:, state it:
Returns a new array that is a copy of the receiving array with a given object added to the end.
Where in the reference does it indicate that addObject: increases the retain count? Given the presence of ARC, I should still understand what these methods are doing to avoid bugs and issues. What does ARC bring to this? (Going to read that again...)
Great question, I'm glad to see someone actually reading the docs and trying to understand them!
Since you are looking for how to research answers using Apple's documentation more so than the actual answer itself, here is how I found the answer:
First I look at the class reference for addObject: which is a method of NSMutableArray and there is no mention of memory management.
Then I look at the Overview section at the top... Hmmm, still no luck.
Since the behavior might be inherited from a parent class, I look at the Inherits from section at the top of the class reference and see that NSArray is the most immediate parent. Let's check there:
Under the Overview There is one small section about retain's:
Special Considerations
In most cases your custom NSArray class should conform to Cocoa’s
object-ownership conventions. Thus you must send retain to each object
that you add to your collection and release to each object that you
remove from the collection. Of course, if the reason for subclassing
NSArray is to implement object-retention behavior different from the
norm (for example, a non-retaining array), then you can ignore this
requirement.
Okay, I'm still not happy... Where next? The parent class of NSArray is NSObject and I know that it won't be covered there in this case (from experience) so I won't bother checking that. (If the parent was another class or something that might be covered by NSObject, I would keep moving up the tree until I found something.)
The Companion Guides usually contains a lot of good information for these types of classes. Let's try the first one, Collections Programming Topics.
The first section (after Overview) is Accessing Indexes and Easily Enumerating Elements: Arrays. Sounds promising! Click on Relevant Chapters: “Arrays: Ordered Collections”
There it is under Array Fundamentals along with a link to even more information:
And when you add an object to an NSMutableArray object, the object
isn’t copied, (unless you pass YES as the argument to
initWithArray:copyItems:). Rather, an object is added directly to an
array. In a managed memory environment, an object receives a retain
message when it’s added; in a garbage collected environment, it is
strongly referenced. When an array is deallocated in a managed memory
environment, each element is sent a release message. For more
information on copying and memory management, see “Copying
Collections.”
The book must be referring to out of date documentation because you are correct it doesn't mention anything about the retain count. It does in fact retain the object though. The way you need to think of it is not in terms of retain counts (which are useless) but rather ownership. Especially so when using ARC.
When you add an object to an NSMutableArray, it is taking ownership of that object (in ARC terminology it has a strong reference to it).
"What does ARC bring to this?"
ARC does nothing different. All ARC does (besides some optimization) is add the same release, retain, and autorelease statements that you would add yourself without using ARC. All you need to care about is that once you add an object to the array, it will live at least as long as the array.
And the arrayByAddingObject: method creates a new NSArray (or NSMutableArray) containing the object you're passing, and keeps a strong reference to the passed object. The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan.
Basically even without ARC, it's best to think of object life-cycles in terms of ownership, ARC just formalizes that. So because of that, when using the frameworks, it doesn't matter when retains happen or don't happen, you are only responsible for your objects until you pass ownership to another object and you can trust that the framework will keep the object alive as long as it needs it.
Now of course you have to intuit what constitutes ownership. For instance delegate properties are often assign, or in ARC unsafe_unretained or weak, to prevent circular retains cycles (where two objects each retain each other), though are sometimes retained/strong so you need to look into those on a case by case basis.
And also in cases like key value observing and NSNotification observing the object you are observing does not retain the observer.
But those are really exceptions to the rule. Generally you can assume a strong reference.
Regarding this sentence above: "The actual array object that it creates has no references yet unless you assign it to either an ivar, property, or local variable. What you assign it to determines it's lifespan." I'll try to explain:
When you run this piece of code: [someArray arrayByAddingObject:someObject]; you've instantiated a new NSArray or NSMutableArray object (depending on which object type someArray is) but you haven't actually assigned it to any reference. That means that if you're using ARC, it may be immediately released afterwards, or if not using ARC, it will be released when it's autoreleasepool is drained (probably on the next iteration of that thread's runloop).
Now if instead you did this: NSArray *someOtherArray = [someArray arrayByAddingObject:someObject]; you now have a reference to the newly created array, called someOtherArray. In this case, this is a local variable who's scope is only within whichever set of { } it resides (so it could be inside an if statement, a loop, or a method. Now if you do nothing else with it, it will die sometime after it's scope ends (it isn't guaranteed to die right away, but that isn't important, you just can't assume it lives longer).
Now if in your class you have an iVar (instance variable) declared in the header like NSArray *someOtherArray; (which is strong by default in ARC) and you run someOtherArray = [someArray arrayByAddingObject:someObject]; somewhere in your class, the object will live until you either remove the reference (someOtherArray = nil), you overwrite the reference (someOtherArray = someThirdArray), or the class is deallocated. If you were not using ARC, you would have to make sure to retain that to achieve the same effect (someOtherArray = [[someArray arrayByAddingObject:someObject] retain]; which is essentially what ARC is doing behind the scenes).
Or you may have a property declared instead like #property (nonatomic, strong) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would achieve the same effect but would use the proprety accessor (setSomeOtherArray:) or you could still use someOtherArray = [someArray arrayByAddingObject:someObject]; to set the iVar directly (assuming you #synthesized it).
Or assuming non-ARC, you might have declared the property like #property (nonatomic, retain) NSArray *someOtherArray in which self.someOtherArray = [someArray arrayByAddingObject:someObject]; would behave exactly as ARC would, but when setting the iVar directly you would still need to add that retain manually.
I hope that clears things up a bit, please let me know if there's anything I glossed over or left out.
As you mentioned in your comment, the key here is intuitively knowing when an object would be considered owned by another one or not. Luckily, the Cocoa frameworks follow a pretty strict set of conventions that allow you to make safe assumptions:
When setting an NSString property of a framework object (say the text property of a UILabel for example) it is always copied (if anyone knows of a counter-example, please comment or edit). So you don't have to worry about your string once you pass it. Strings are copied to prevent a mutable string from being changed after it's passed.
When setting any other property other than delegate, it's (almost?) always retained (or strong reference in ARC)
When setting delegate properties, it's (almost?) always an assign (or weak reference) to prevent circular retain cycles. (For instance, object a has a property b that is strong referenced and b has a strong referenced delegate property. You set a as the delegate for b. Now a and b are both strongly referencing each other, and neither object will ever reach a retain count of 0 and will never reach it's dealloc method to dealloc the other object. NSURLConnection is a counter-example that does strongly reference it's delegate, because it's delegate is set via a method -- see that convention below -- and it's convention to nil out or release an NSURLConnection after it completes rather than in dealloc, which will remove the circular retain)
When adding to an array or dictionary, it's always retained (or strong reference).
When calling a method and passing block(s), they are always copied to move them from the stack (where they are initially created for performance purposes) into the heap.
Methods that take in object parameters and don't return a result immediately are (always? I can't think of any that don't) either copying or retaining (strong referencing) the parameters that you pass to ensure that the method can do what it needs to with them. For instance, NSURLConnection even retains it's delegate because it's passed in via a method, whereas when setting the delegate property of other objects will not retain, as that is the convention.
It's suggested that you follow these same conventions in your own classes as well for consistency.
Also, don't forget that the headers of all classes are available to you, so you can easily see whether a property is retain or assign (or strong or weak). You can't check what methods do with their parameters, but there's no need because of the convention that parameters are owned by the receiver.
In general, you should look in the "most global" spot for information about anything in the Cocoa APIs. Since memory management is pervasive across the system APIs and the APIs are consistent in their implementation of the Cocoa memory management policy, you simply need to read and understand the Cocoa memory management guide.
Once understood, you can safely assume that all system APIs implement to that memory management policy unless explicitly documented otherwise.
Thus, for NSMutableArray's addObject: method, it would have to retain the object added to the array or else it would be in violation of that standard policy.
You'll see this throughout the documentation. This prevents every method's documentation from being a page or more long and it makes it obvious when the rare method or class implements something that is, for whatever reason (sometimes not so good), an exception to the rule.
In the "Basic Memory Management Rules" section of the memory management guide:
You can take ownership of an object using retain.
A received object is normally guaranteed to remain valid within the
method it was received in, and that method may also safely return the
object to its invoker. You use retain in two situations: (1) In the
implementation of an accessor method or an init method, to take
ownership of an object you want to store as a property value; and (2)
To prevent an object from being invalidated as a side-effect of some
other operation (as explained in “Avoid Causing Deallocation of
Objects You’re Using”).
(2) is the key; an NS{Mutable}Array must retain any added object(s) exactly because it needs to prevent the added object(s) from being invalidated due to some side-effect. To not do so would be divergent from the above rule and, thus, would be explicitly documented.

Clarification on custom init methods / pointers in general for objective c objects

When I have my own init method with synthesized properties as such:
#property (copy, nonatomic) NSString *bookName;
#property (strong, nonatomic) NSMutableArray *book;
When I want to initialize with my own custom initializer I am shown to write it like this:
-(id) initWithName: (NSString *)name
{
self = [super init]
if (self) {
bookName = [NSString stringWithString: name];
book = [NSMutableArray array];
}
return self;
}
Now I want to clarify something. I know why it uses the stringWithString method, because instead of just passing the address to the passed in string it'll create a new object so that it owns the string itself. Could I not also just write it like so:
self.bookName = name;
Doing this should use the synthesized method and actually create a new object right? Basically both accomplish the same thing. I ask because there are methods else where that show doing it both ways so I just want to make sure there are no other issues that could crop up with using one way or the other. They both appear to do the same thing in different ways (using the synthesized method vs directly modifying the class variable but creating a new object in memory for it).
I'll also point out that this is in an ARC environment.
(Note that I am assuming the above is ARC code; otherwise it is incorrect.)
You should almost always use accessors to access your ivars (even in ARC). However, there is some controversy about whether init should use accessors or directly access its ivars. I have switched sides in this controversy, but it's not an obvious decision IMO.
The primary argument for not allowing init to use accessors is that it is possible that a future (unknown) subclass might create side-effects in the accessor. You generally don't want side effects happening during your init. For instance, you probably don't want to post change notifications when you're setting something to its initial value, and it is possible that your object is in an "undefined state" and would be dangerous to read at this point.
That said, and while this argument did finally sway me, I have never once encountered this situation on numerous projects of various sizes with several teams. I have many times encountered developers failing to retain when setting their ivars in init (as you have done above, and which would crash if it is not ARC). This is why for a long time I recommended using accessors even in init. But in theory it does create a danger, particularly if you are a closed-source framework writer (i.e. Apple). And so, for my own code I now avoid accessors in init. If I were working with a more junior teams on older retain/release code, I would probably still have them use accessors in init. It's just avoided so many crashes in my experience.
It is not controversial that you should avoid calling accessors in dealloc, however. This definitely can lead to bizarre side-effects in the middle of destroying your object.
You are correct, since bookName is declared as copy, assigning self.bookName would make a copy of the string passed in. I am not certain that copying would go through exactly the same code path as the [NSString stringWithString: name], but it would achieve the same purpose of creating a copy of the original string, shielding you from unexpected consequences of users passing in a mutable object and mutating its value behind your back.
Because the declared property is copy then yes, they are doing the same thing.
Many times however, it is a strong and then there would be a difference between the two methods so the first method would be the "correct" way of doing it.

Initializing several ivars of the same type with same object?

So, this is pretty standard memory management, from what I understand:
ClassName *temp=[[ClassName alloc] init];
self.ivar=temp;
[temp release];
This is to avoid the memory leak created by just doing this:
self.ivar=[[ClassName alloc] init];
Cool. But, suppose I have several ivars that are based ClassName? Is this okay:
ClassName *temp=[[ClassName alloc] init];
self.ivar=temp;
self.othervar=temp;
self.anothervar=temp;
[temp release];
Would they all be manipulating the same object, ultimately, even though I want them to have different instances of ClassName? I assume that the outcome of this might depend on if the ivars were created as retain vs copy? Suppose they are set to retain, would this be okay?
Would they all be manipulating the same object, ultimately, even though I want them to have different instances of ClassName?
the default expectation is "yes, they would reference the same object because this is a reference counted system."
I assume that the outcome of this might depend on if the ivars were created as retain vs copy?
not might, but entirely. if the property is declared copy and the type adopts NSCopying, that should be all that is needed. if you implement the setters (what are often synthesized properties) yourself, you must copy in your implementations.
Suppose they are set to retain, would this be okay?
then they would all refer to the same instance. whether that is the correct semantic for your program depends on how you need it to behave. in this example, you stated "I want them to have different instances of ClassName" so you would either need to create an unique instance for every destination (either directly or via copy, if ClassName adopts NSCopying).
If the properties are all retain then you will be storing the same instance three times, as you assume. If you want different instances, and you want to use retain, then you need to create three different instances. copy will create a copy, but then it will do this every time you set anything to the property, which may not be your desired behaviour.
In your example all objects will point/manipulate same object instance unless they are
copy/mutableCopy
or any other type that conforms to NSCopying protocol.
retain will have no affect other than incrementing retainCount of an already allocated object.

In Objective-C on iOS, what is the (style) difference between "self.foo" and "foo" when using synthesized getters?

I have searched many questions on ObjC accessors and synthesized accessors to no avail. This question is more of a "help me settle an issue" question; I don't expect one answer, but I'm rather looking for experts to weigh in on the argument.
In a Cocoa Touch class, I would write some code like this (where soundEffects is a synthesized NSArray property):
id foo = [self.soundEffects objectAtIndex:1];
A colleague asked me to explain why the above is any better than this line:
id foo = [soundEffects objectAtIndex:1];
Well, functionally, it's no different.
My arguments for the former are as follows:
self.soundEffects tells every other coder working on the code that this is an iVar, not a locally scoped variable.
If we ever needed to, we could put custom logic in the soundEffects getter accessor.
For no concrete reason, it "feels" like the right thing to do after working in Obj-C for a year.
He accepts arguments #1 and #2 as valid, but also gives the counterpoint:
Isn't this just code bloat?
Shouldn't a class be allowed to talk to its own iVars directly without having to call a method (the getter) on itself?
Any takers?
I have personally settled on using an underscore prefix for ivars, and this kind of synthesize
#synthesize name = _name;
That way I don't mix them up. The major issue with not using self is that this code
_name = ...
is very different from
self.name = ...
When the #property uses the retain option. The first does not retain the object, and the second calls the synthesized setter that retains.
The only time it makes a big difference is with assigning, so I tend to use self. all of the time so I make sure I do it on assigns.
Your point 1 is not quite right: self.soundEffects is not an ivar, although it may happen to give you something which is -- as it does in the case of your synthesized NSArray, at the moment.
This in turn implies that your point 2 is the crux of the matter -- if you route all access through the accessor, then everything is nicely encapsulated and you're free to modify the implementation later without having to worry about side effects.
It's also good practice for when you use the mutator, so you maintain consistent memory management.
For the most part, I'd say it's advisable to route through self.property for everything that is a property, and restrict direct ivar access to things which are strictly internal. However, I'll admit that in some cases -- especially for things that don't use retain/copy semantics -- it can be more of a style preference.
using something like self.variable = nil makes the variable go through its setter and therefore gets memory managed for free. if you just use variable = nil for instance in a dealloc method, it will cause a leak since it is not actually going through the synthesized setter for the variable and decreasing the retain count. See this post memory leak with self.
For this reason, it is advisable (i believe) to always use self. when dealing with instance variables that you own as far as memory management is concerned.
self.soundEffects sets/gets the instance variable through the setter/getter, and hence if we want to do some custom operations when their value changes, that logic can go in their getter/setter.
Also as per ios 6, the ivar corresponding to
#property (nonatomic)NSArray *propertyName;
will be _propertyName
so i guess you cant use id foo = [soundEffects objectAtIndex:1]; anymore.Not sure though.Instead you should use id foo = soundEffects[1];

Do I need getters and setters if i'm depending on garbage collection in objective-c

New to Cocoa and Objective-c.
Do I need getters and setters if I'm depending on garbage collection?
For example is it safe to just modify instance variables directly without the dot syntax?
And in the dealloc method can I sent them to nil instead of release (or do I even have to release them)?
Property (Getters and setters) is a mean of encapsulation, and ivar is an implementation detail.
Accessing via properties allow you to change the internal design while keeping the interface unchanged.
Whether the program has GC enabled or not, you shouldn't access ivar directly externally (internally is fine).
(Also, the -dealloc method is ignored if GC (not ARC) is enabled. You could implement -finalize. But the GC should be smart enough to clean the no-longer-needed ivars, whether to set them to nil or not.)
From within the class itself you can directly modify the private variables of course. Think about accessors mainly to expose a public interface and avoid other classes to modify directly your object. This comes from the Object Oriented Paradigm and not with the memory management.
About the release it is better to understand clearly how it works using the retain count and what have a role on that count. Some method like init increase retains the object and some other do not. A lot static methods that return new ready to use object like imageWithNamed: return an autorelease object that you have to retain explicitly to own them.
The best is to release and set to nil when you have transfer the ownership to another object (ex. an array)
ex.
NSString *myName = #"zgueb";
NSArray *myFamily = [[NSArray alloc] initWithObjects:myName, nil];
// now myName is retained by myFamily, i can release it
[myName release];
myName = nil;
Is it clear.
Vince.