What is the role of keyword copy in the ARC
I find the copy(keyword) can be used in ARC while retain and release cannot be used. Moreover is the role of copy in ARC is the same as the role of copy in MRC? If yes , does copy make the retainCount +1 in ARC?
And I have seen mike ash blog about ARChe said :
you need to explicitly copy blocks that you pass as id parameters:
[myArray addObject: [^{ DoSomethingMagical(); } copy]];
but when I test code like this (without using copy) it works well too.
NSArray *array = [[NSArray alloc] initWithObjects:^{NSLog(#"hahaha");}, nil];
[self test:[array objectAtIndex:0]];
- (void)test:(void (^)(void))completion
{
completion();
}
Does it mean that there is no need to copy block when it used as an id type?
Yes , the role of copy in ARC is the same as the role of copy in MRR
The copy will invoke the copyWithZone: method . when it send to the mutable object , it will return a clone immutable object , which retainCount is 1. When it send to the immutable object , it will not copy , it will return the object itself , but the retainCount +1.
So when you use copy in ARC , you can use like this : object1 = [object2 copy]; ARC will manage the retainCount of the object1 , when then object1 is released by ARC , the object2's retainCount will be a corresponding change. So you do not worry about the memory.
About the block need be copy when pass as id parameters.
the apple document said :
Typically, you shouldn’t need to copy (or retain) a block. You only
need to make a copy when you expect the block to be used after
destruction of the scope within which it was declared. Copying moves a
block to the heap
and As ughoavgfhw said :
Blocks are similar to other objects for memory management, but not the
same. When a block which accesses local variables is created, it is
created on the stack. This means that it is only valid as long as its
scope exists. To save this block for later, you must copy it, which
copies it to the heap
Copy does just what the name implies. It returns a copy of the object. Say you have a mutable object and you have a pointer to it. You then reference it somewhere else in the code and ARC will assume you want to point at the same object and retain it for you. In this case if you modify either of them both will reflect the changes. If you point at it with a copy you will get a new object, and modifying one will not affect the other:
NSMutableArray* objA = [NSMutableArray new];
NSMutableArray* objB = objA;
/* adding an object to either will be in both since they point to the same object*/
objB = [objA mutableCopy];
/*adding an object to one WILL NOT affect the other, they are different, distinct objects*/
In the docs here:
http://developer.apple.com/library/ios/#documentation/cocoa/Conceptual/Blocks/Articles/bxVariables.html#//apple_ref/doc/uid/TP40007502-CH6-SW1
It mentions that when blocks are copied all of their Objective-C Objects receive a strong reference so that they don't drop out of scope before the block is executed.
When you use copy in ARC, it does the same as without ARC, i.e. it creates a copy of the object that is receiving the copy (it creates a new object instance in memory), and creates a strong relationship to the object that executes the code.
This means that the copy of the object now has a retain count of 1, but this is of no relevance for you in ARC, since this is handled automatically.
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]
So if I have:
SomeBlock myBlock = ^(){};
[self.mutableArray addObject: [myBlock copy] ];
later if I need to:
[self.mutableArray removeAllObjects];
then should I first go through all the blocks in the array and release each of them?
Thanks
Edit:
I am not using ARC, and I saw somewhere when I add a block to array I need to copy it, that's why I do [block copy] when I add it to array, thus I thought that I should release them before I remove all objects from the array.
I am assuming that you are not using ARC (the question would not be interesting then).
In your code, you do need to send release to all of your blocks:: although NSArray retains objects placed into it, and releases objects when the array itself is released, the objects that you add already have a retain count of 1, because copy method gives you an object with a retain count of 1. That is why you need to follow copy with autorelease before adding your block to the array, like this:
[self.mutableArray addObject: [[myBlock copy] autorelease]];
Whenever you get the ownership of any object, it is yours duty to release it otherwise a memory leak will happen.
If you don't release your pointer to that object, it will be a leak.
When you release the array, it will call release on all of the objects
that it holds, since it called retain previously.
For ARC, it will be in autorelease so you need to release yourself.
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 need to understand why in this code i get a memory leak if i assign value to ws_data variable using self.ws_data and not if i use only ws_data.
self.ws_data is a #property (copy)NSString *, released on dealloc.
dispatch_queue_t ws_queue = dispatch_queue_create("ws check win", NULL);
dispatch_async(ws_queue, ^{
self.ws_data = [[NSString alloc]initWithContentsOfURL:url];
});
dispatch_release(ws_queue);
Thank you!
self.variableName accesses the variable through its accessors. Because your ws_data NSString is set to copy in its property declaration, the string is retained when you set it through that declaration.
Not using self. references the ivar without going through those accessors. It also means the variable isn't copied, so it will vanish when references to it disappear (like at the end of your method).
Odds are you want the copy. You just need to release it when you're done, as you do in your dealloc.
Are you retaining it somewhere else, making this access a second retention?
If I understand things correctly (and I quite possibly don't as I've not be doing iOS development for very long at all) in this instance, as you're using the copy attribute on the property, what you're doing when you use self.ws_data is effectively calling the copy method on an already alloced NSString, which is creating a separate instance of the NSString with a retain count of one.
However, the original NSString (that's being alloced in your above sample) isn't being released at any point, hence the leak.
You could use...
self.ws_data = [[[NSString alloc]initWithContentsOfURL:url] autorelease];
...instead, I'd have thought.