So, I am wondering whats the difference between these two segments of code - other than just syntax differences?
BBDataStore* tempDataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
self.dataStore = tempDataStore;
and
self.dataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
Self.dataStore is a property of BBDataStore.
From what I can see - there is no difference here.
In the first example - we eventually assigned tempDataStore to self.dataStore - which is an instance of BBDatastore.
In the second example - we effectively do the same thing... not so?
BBDataStore* tempDataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
self.dataStore = tempDataStore;
This is holding instance of BBDataStore into tempDataStore. And you are assigning tempDataStore to other object say self.dataStore.
self.dataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
This is the direct initialization of self.dataStore.
Difference is only that in first way one more variable come in picture which also consumes memory bit. Why should we consume memory even we have handy approach for initiazation. So you should avoid first way and go with second approach which is very general and appropriate too.
If you are using ARC in your code, both the statements are effectively doing the same (compiler magic happens which ensure both statements end up with same result).
If this were manual memory management with self.dataStore declared as a retain property then,
Code1: Will be ideal way to assign the retain property with an object. This will keep the reference count of the created object to 1 (Your property will be the owner). So when the ivar for the retain property is released in dealloc the memory gets cleared.
BBDataStore* tempDataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
self.dataStore = tempDataStore;
//This will ensure memory does not leak, reference count will get reduced by 1
[tempDataStore release];
Code2: Will have reference count of the object as 2 (One from init and other from retain property). Even after releasing the ivar in dealloc this code will potentially leak memory since the temporary object reference is not available to call release method.
//This created object will have reference count 2
self.dataStore = [[BBDataStore alloc] initWithDataExpiry:DATA_EXPIRY_TIME];
//reference to temporary object is not available hence cannot call release
So in this case for the ARC mechanism the compiler will insert certain lines of code to ensure that memory of your object does not leak (It will create a temporary reference to object, insert release statement on this after assigning to the property, similar to code1).
Hope that helps!
In First case first line creates an object and tempDataStore has reference to it, when second line execute, self.dataStore also point to the same object. hence reference count will increase and two pointers will point to same object. And when tempDataStore scope will end there will be only one reference to the object and that will be self.dataStore. And in second case there is only one pointer reference to object and that is self.datastore
Related
When you write code like below in ARC
__weak NSMutableArray* array = [[NSMutableArray alloc] init];
The compiler will show you a warning or error and say "Assigning retained object to weak variable. object will be released after assignment".
But if you write like this:
__weak NSMutableArray* array = [NSMutableArray array];
There is no error.
I'm wondering if the second usage is reasonable in some situations? What's the difference between these two codes from memory management perspective? How does it work?
There can be very subtle differences that the compiler cannot know.
Let's take an immutable version: [NSArray array] could return the very same static object every time. So your weak variable will point to a valid object, that has a strong reference somewhere else. Or think of the singleton pattern. On the other hand, when calling alloc/init, convention dictates that you're the only owner of that object, and that will typically leave you with nothing.
Also, the factory method certainly looks more like a (functional) method. In any case, it doesn't communicate ownership of what it returns very well. For an autoreleased object, it's not clear whether you're the the only owner or a shared owner.
They are the same because you lose the object instantly. Compiler cannot know probably, except alloc init, that the object will be lost.
In the first form, the method returns a retained object. ARC ensures, that the object is released when there is no strong reference on the call-site. This is immediately true, with the weak reference - thus, the compiler emits a warning or error.
In the second form, the method returns an unretained object. In this case, the compiler must ensure that the object is still valid across the return boundary. 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. That is, there is a strong reference created by the compiler. This strong reference will be automatically released by the compiler generated code.
Thus, in this case there's no error or warning.
In the worst case, holding that object may require to use an autorelease pool. However the compiler can apply certain optimisations which avoids this. Thus we should not assume that the returned object lives in an auto release pool.
See specification: http://clang.llvm.org/docs/AutomaticReferenceCounting.html#id14
See also this question on SO: Difference between [NSMutableArray array] vs [[NSMutableArray alloc] init]
I had developed an app and now I'm using Instruments to see the memory usage. I have a problem understanding the retain/release process of my object. This is what Instruments says:
The retain count increase when I add my object into an array, when I add it on my view and when I take off from the array.
So, when I use removeFromSuperview the object retainCount will never be zero, so the object don't release the memory.
EDIT 1:
I forgot to say i'm using ARC.
EDIT 2:
I describe exactly what happen :
I create the object together other objects in a class called NKLevelGenerator. Into it i alloc the NKIngredients and then i add all to a NSArray which will be returned. Here the retain count of every object is 2. In my NKLevelVC, my ViewController, i use this instruction :
[level addObjectsFromArray:[levelGenerator level1WithDelegate:self ciotola:ciotola bagliore:bagliore difficulty:NKDifficultyHard]];
Object level is a NSMutableArray that i alloc and init in viewDidLoad.
From here i call another method which performs this operations :
- (void)insertInArrayRandomly {
for (int i=0; i<[level count]; i++) {
[ingredienti insertObject:[level objectAtIndex:[[indexes objectAtIndex:i]integerValue]] atIndex:i];
}
}
Object ingredienti is another NSMutableArray that I alloc and init in viewDidLoad. indexes is an array of NSInteger which contains random indexes to extract NKIngredient object randomly.
Then i'm doing this :
NKIngredient *ing = [ingredienti objectAtIndex:index];
[[self view] insertSubview:ing belowSubview:navBar];
[ing animateIngredient];
[ingredienti removeObject:ing];
Before looking into Instruments have you tried the Static Analysis of your code? It may help for simple memory problems.
But the very first thing to check is: Did you follow the Golden Rule?
The Golden Rule being: For each alloc, copy or retain you must use one, and only one, releaseor autorelease.
This is the most important rule for memory management without ARC. So the fact that you object is retained by th array is none of your business, just remember what you have retained, allocated or copied and release it.
PS: Next time, your code would be much more helpful than the Instruments screenshot.
First: use instruments to see if effectively there's a memory leak, there's a tool made for this purpose and it tells you where you leak memory.
Second: it depend on how many object made [retain] on the view. If you add to an Array, it retain the view, but if you don't release it in the method that create the view, when you release the view from the array, the count will still be 1.
I couldn't get the right answer for this question. If it is found duplicate, please make it duplicate with the right reference link.
I wanted to know, what are the ways the reference count is incremented. I know, alloc/init and retain increases the reference count, does 'copy' also increases the reference count to '1' ?
Thanks.
copy creates a new object which is, as the method name suggest, a carbon copy of the receiver (well in fact it depends of the implementation of the copy method in each class, but that's the aim of the method anyway).
So in fact it does not really "increase the reference count of the by 1" but it rather create a new object, with a refcount of 1 as any newly allocated object, and make it have the same property / ivar values as the original.
So imagine you have a Person class with the properties name, surname and age, if you needed to implement the copy method yourself it would look sthg like this:
-(id)copy
{
// Create a new instance
Person* mycopy = [[Person alloc] init];
// Make it an exact copy of the original
mycopy.name = self.name;
mycopy.surname = self.surname;
mycopy.age = self.age;
// and return that copy
return mycopy;
}
Note that in this case, if you modify the copy later, the original is not modified, because it is a different instance.
With this principle, the original object does not have its refcount incremented by one, but you have a new object whose refcount is one (as if you just did alloc/init to create this new object yourself) and you still have to release or autorelease it at some point yourself (if you are not using ARC). That's why calling copy on an object obey the same rules as retain or alloc regarding the need to call release or autorelease to balance the refcount at some point
Note that there is some exceptions / special cases, especially for some classes that are known as "immutable", like NSArray or NSString. In such cases, it is reasonable to thingk that making a copy (aka a different object instance) that is a clone of the original, whereas the original cannot be modified, is not really efficient, and can be optimized.
So in cases like NSArray and NSString and some other, the copy method may simply implemented to do a simple retain as the behavior will be the same as you can't modify the original (and neither the copy) because these are immutable classes by nature.
Of course, the implementation of mutableCopy (to get an NSMutableArray from an NSArray for example) do a real copy and not a simple retain, and the implementation of the copy method in the mutable subclasses like NSMutableString and NSMutableArray do a real copy too, but for the case that request an immutable copy of an immutable object, the point of allocating a different instance is generally useless and memory-consuming and is thus implemented the same as a retain.
But all this probable optimization does not change neither the behavior (because the classes are immutable) nor the memory management policy (as you still need to release the object returned by copy)
I'm new to Objective C. I have basic knowledge in C, including the concept of pointers. I have two basic questions:
Can someone explain the difference between assign,copy, and retain with some analogy?
How do you handle a function which returns pointer variable, and how do you perform messaging through a return pointer?
Updated Answer for Changed Documentation
The information is now spread across several guides in the documentation. Here's a list of required reading:
Cocoa Core Competencies: Declared property
Programming with Objective-C: Encapsulating Data
Transitioning to ARC Release Notes
Advanced Memory Management Programming Guide
Objective-C Runtime Programming Guide: Declared Properties
The answer to this question now depends entirely on whether you're using an ARC-managed application (the modern default for new projects) or forcing manual memory management.
Assign vs. Weak - Use assign to set a property's pointer to the address of the object without retaining it or otherwise curating it; use weak to have the property point to nil automatically if the object assigned to it is deallocated. In most cases you'll want to use weak so you're not trying to access a deallocated object (illegal access of a memory address - "EXC_BAD_ACCESS") if you don't perform proper cleanup.
Retain vs. Copy - Declared properties use retain by default (so you can simply omit it altogether) and will manage the object's reference count automatically whether another object is assigned to the property or it's set to nil; Use copy to automatically send the newly-assigned object a -copy message (which will create a copy of the passed object and assign that copy to the property instead - useful (even required) in some situations where the assigned object might be modified after being set as a property of some other object (which would mean that modification/mutation would apply to the property as well).
The Memory Management Programming Guide from the iOS Reference Library has basics of assign, copy, and retain with analogies and examples.
copy
Makes a copy of an object, and returns it with retain count of 1.
If you copy an object, you own the copy. This applies to any method that contains the word copy where “copy” refers to the object being returned.
retain Increases the retain count of an object by 1. Takes ownership of
an object.
release Decreases the retain count of an object by 1. Relinquishes
ownership of an object.
NSMutableArray *array = [[NSMutableArray alloc] initWithObjects:#"First",#"Second", nil];
NSMutableArray *copiedArray = [array mutableCopy];
NSMutableArray *retainedArray = [array retain];
[retainedArray addObject:#"Retained Third"];
[copiedArray addObject:#"Copied Third"];
NSLog(#"array = %#",array);
NSLog(#"Retained Array = %#",retainedArray);
NSLog(#"Copied Array = %#",copiedArray);
array = (
First,
Second,
"Retained Third"
)
Retained Array = (
First,
Second,
"Retained Third"
)
Copied Array = (
First,
Second,
"Copied Third"
)
assign
assign is a default property attribute
assign is a property attribute tells the compiler how to synthesize the property’s setter implementation
copy:
copy is required when the object is mutable
copy returns an object which you must explicitly release (e.g., in dealloc) in non-garbage collected environments
you need to release the object when finished with it because you are retaining the copy
retain:
specifies the new value should be sent “-retain” on assignment and the old value sent “-release”
if you write retain it will auto work like strong
Methods like “alloc” include an implicit “retain”
I've people who use [variable release] and some other times variable = nil to clean up memory?
When do you use each one? and what are the differences?
variable = nil; will not release memory. self.property = nil; will release memory if [self setProperty:nil]; would, for example a synthesized property with the retain attribute. Calling [variable release]; will always release one reference of an object.
Depends on what you mean by "clean up memory".
release is the only thing that frees dynamically allocated memory allocated by alloc. alloc should always be paired with a call to release or autorelease somewhere.
Setting a varible to nil does not necessarily free any memory (see drawnonward's answer), and can be a source of memory leaks.
When you see a variable set to nil, it's about preventing it from accidentally being used later after its memory has been freed (this can cause crashes). While you can always set a variable to nil after a call to release, it's somewhat a matter of style when it's actually necessary. For example, you don't often see variables set to nil in the dealloc method of a class, since by that point an object won't be able to accidentally misuse such a variable anymore, since it's being nuked.
If a property is set to retain, then these 3 are equivalent:
[self setProperty:nil];
self.property = nil;
[property release]; property = nil;
In each case, the object will be released, and then set to nil so that all access to the object from then on will not be allowed. "nilling" the instance variable is handy since it ensures you can only ever release the object once in this context because calling self.property = nil twice will do nothing the second time, but calling [property release] will release the object twice even though you likely only retain it once.
Most of the time I find it least bug prone to let retain properties do their thing and try to stay away from explicit retain and release calls most of the time.