My knowledge of ARC has been tested today, i stumbled on this article and it has an example under the heading "Nesting of statements" which in my mind seems wrong.
In the example they show embedded above, the line highlighted with a green underline says that the string alloced inside the function would first get a retain count +1 when being created, then +1 again when adding to the array, then once the array is nil'ed after the for loop, the retain count of the string would be reduced by 1, leaving the original string with a retain count of 1, thus not being dealloced.
I would have assumed the compiler would have been smart enough to at least make an object like that not actually have a retain count initially, since if you just had
[[NSString alloc] initWithFormat:#"Name 1"]];
this string being alloced would have nothing pointing to it and would be released when the autorelease pool comes to an end instead of having a retain count of 1 forever. so why would it have different behaviour when its in a parameter of a function? (unless that line does have a retain count of 1 and this is somehow a memory leak? otherwise it could have a retain count of 1 till the end of its scope at most surely, but then that logic would apply if its a parameter as well i would assume)
Is this article wrong or is my understanding of ARC flawed?
The article is wrong.
Your understanding is essentially correct, though the autorelease pool is not used in this case. The sub-expression:
[[NSString alloc] initWithFormat:#"Name 1"]];
returns an owned object, as do all init methods. That object is passed to addObject: and the array also takes ownership. After that ARC sees the string is no longer required by the method and relinquishes its ownership - leaving the array as the only owner.
HTH
ARC is not flawed here. Sounds like the article is wrong.
ARC will release the allocated parameter object as expected while the array keeps its reference. Once the array is released, the object will have no more references and it will also be deallocated, as expected.
NSMutableArray is not thread-safe, but I don't see why they can't be designed to be thread-safe as long as different indices are being manipulated simultaneously. E.g. Index 1 points an instance of class X and Index 2 to another instance. Isn't it efficient to allow these two objects to be manipulated at the same time? Is this allowed when I use GCD or do I need to use a dispatch barrier when I am changing objects pointed to by different indices?
Think of it like this.
Your array contains pointers to objects. Pointers are essentially signposts, pointing to where the objects are located in memory.
Now when you mutate an object, you don't actually touch any pointers to the that object. The object's location in memory is unaffected.
Therefore, from the array's point of view, nothing happens when you mutate the objects themselves in it, as the pointers remain unaffected. This means that mutating different objects in an array from different threads is perfectly safe.
Therefore, you are correct when you say it's more efficient to download your data in parallel into different objects in your array.
So long as you're not mutating the array itself (adding or removing objects) or mutating the same object concurrently, you'll be fine.
If you do need to mutate the array from multiple threads simultaneously, you are right in saying you should use a concurrent queue, with a barrier to write, and a standard dispatch to read. This will allow for multiple concurrent reads (which is perfectly safe) and will serialise writes with reads.
I have an instant variable "obj1" in MyClass.h.
#property (nonatomic, retain) NSMutableArray *arrObj1;
and in MyClass.m viewDidLoad method, i have allocated another object "obj2" and assign that to obj1.
- (void)viewDidLoad {
[super viewDidLoad];
NSMutableArray *arrObj2 = [[NSMutableArray alloc] initWithObjects:#"a",#"b",#"c", nil];
NSLog(#"arrObj2 count %lu",(unsigned long)[arrObj2 retainCount]);
self.arrObj1 = arrObj2;
NSLog(#"arrObj1 count %lu",(unsigned long)[self.arrObj1 retainCount]);
NSLog(#"arrObj2 count %lu",(unsigned long)[arrObj2 retainCount]);
}
Here is the output
2015-08-19 11:06:14.461 MyClass[1812:24133] arrObj2 count 1
2015-08-19 11:06:16.332 MyClass[1812:24133] arrObj1 count 2
2015-08-19 11:06:17.327 MyClass[1812:24133] arrObj2 count 2
I am not getting how arrObj2 get retain Count value 2.
please explain me.
Thank you
A more relevant question to your problem is: Why do arrObj and arrObj2 seem to share properties? And the answer is they're two references to the same object. That means the same array is referenced strongly in the same place; that is, arrObj1 and arrObj2 are actually the same array. That's why you see a retainCount of 2, though you shouldn't use retainCount for this. (More on that later.) Compare the addresses of the arrays in the debugger instead; they will be the same. If you add an object to one array, it'll be added to "the other."
You can fix that by using copy on the property declaration instead, or by changing self.arrObj1 = arrObj2 to self.arrObj1 = [arrObj2 mutableCopy] . (Edit: I'm not actually sure changing the property type to copy will help here, since it's a mutable type. It would work if it was just an NSArray, though.)
I hope that answers your question, but now I want to explain why it's the wrong question. Please don't take any offence, because learning this is important and not easy. :)
Think in terms of relationship type, not retain/release
You shouldn't be thinking in terms of retain counts at all, but in terms of strong and weak relationship: A strong relationship expresses an ownership interest in the object, a weak relationship doesn't and will be converted to nil shortly after all ownership interests in the object are removed. Also, note that the retain property type is deprecated: it should be strong in ARC code.
Don't use retainCount.
Don't use retainCount. Or, if you prefer, When to use Retain Count:
Never.
Then there's Apple's official documentation, which begins:
This method is of no value in debugging memory management issues.
Or there's this from bbum, which I consider even better. He goes into great detail about why retainCount is useless, concluding with:
Bottom line: the only time the absolute retainCount can be conclusively used for analytic purposes is if you have the backtrace of every retain and release that contributed to the current retain count’s value (there is another use case, documented at the end). If you have that, then you don’t need the retain count and, fortunately, Instruments is already generally quite adept at producing a per-object inventory of retains and releases for you.
Basically, it's value is not useful. It will return (in some cases) the number of times an object has been retained without releasing. It does not (and can not) take the number of times it has been autoreleased into account. And it will not always return the "correct" value even without considering autorelease, since some objects can never be deallocated from RAM.
in Objective-C an object is a reference type.
The retain count is increased the first time when the object was allocated.
When the object is assigned to arrObj1 the object is not copied when the property is declared as retain or strong so arrObj1 and arrObj2 contain the pointer to the same object. The implicit setter of the property arrObj1 increases the retain counter a second time.
Memory management is the programming discipline of managing the life cycles of objects and freeing them when they are no longer needed.
Managing object memory is a matter of performance; if an application doesn’t free unneeded objects, its memory footprint grows and performance suffers.
Memory management in a Cocoa application that doesn’t use garbage collection is based on a reference counting model. When you create or copy an object, its retain count is 1.
Thereafter other objects may express an ownership interest in your object, which increments its retain count.
The owners of an object may also relinquish their ownership interest in it, which decrements the retain count. When the retain count becomes zero, the object is deallocated (destroyed).
Check this image.
https://developer.apple.com/library/ios/documentation/General/Conceptual/DevPedia-CocoaCore/Art/memory_management.jpg
Hope this help.
After the statement
self.arrObj1 = arrObj2;
the variable arrObj2 and the property self.arrObj1 point to the very same object.
If they point to the same object, and arrObj2 has a reference count of 2, what reference count do you expect self.arrObj1 to have?
Reason why retain count is coming as 2 is because you have used retain for NSMutableArray *arrObj1, so in effect
when you allocate arrObj2 retain count become 1,
the when you assign it to arrObj1 as its having a retain property, count increase - becoming 2.
arrObj2 is same arrObj1 as you have not copied it (as Steven Fisher in above answer pointed out) both has same retain count.
If you make arrObj1 to assign property then count will be remained as 1.
Simply put, the object pointed to by arrObj2 is the same object pointed to by arrObj1. Instruments shows us that this object gets +1 retain count when you called initWithObjects:
And that it got +2 retain count when you called setArrObj1 (i.e. you used the self.arrObj1 = ... syntax):
For demonstrations using Instruments' "Allocations" tool for tracking memory usage, see WWDC 2013 video Fixing Memory Issues and WWDC 2012 video iOS App Performance: Memory. Bottom line, while it will take some practice to efficiently find the correct objects in the "Allocations" tool, this "Record reference counts" feature is invaluable in finding where the strong references to the objects in question were established.
I'm sure you've seen it, but I'd also refer you to the Advanced Memory Management Programming Guide.
When you alloc a new memory area (I call it M) and assign it to obj2, the retainCount of M is 1.
When you do: self.obj1 = obj2.
Because self.obj1 is a retain property, so M will be retain +1, so its retainCount = 2 now.
Cause obj1 & obj2 are references to M, so their retainCount are 2.
Let try [obj1 release] and get retainCount of obj2 again to check.
Hope it helps.
Wondering, After building nsmutablearray should i convert it to nsarray for performance benefit? If i am going to keep and use that array for quite sometime.
No. The conversion itself will cost time and CPU cycles and you won't gain anything from the conversion.
I would actually say it depends. If I create a NSMutableArray within a method and needs to return it, then generally unless the caller requires the ability to directly modify the array values, I will return the NSMutableArray as a NSArray for the sake of simlicity and to reduce the memory footprint of the application.
However, if I am creating the NSMutableArray for direct consumption within the current method, then I seen no benefit of casting it to a NSArray.
I have a question regarding NSArray and NSMutableArray. I understand the difference between two primarily that NSArray is immutable and NSMutableArray is mutable. And as far as my research goes, there performance is kind of same too. There is one thing that I could not find a good answer for and that is if NSMutableArray uses more memory than NSArray and if NSMutableArray is somehow harsher on memory than NSArray.
I would really appreciate the suggestions and explanation.
Thanks
Vik
NSMutableArray uses slightly more memory for two (er, four, see comments) reasons:
1) Because it can change size, it can't store the contents inside the object and must store a pointer to out of line storage as well as the extra malloc node for the storage
2) Because it would be very slow to resize one element at a time as things are added, it resizes in chunks, which may result in some unused space.
It's like wondering about the difference between a standard array or a std::vector. A mutable data structure does require to do more things, not primarily memory (as the one required by NSMutableArray and NSArray could be equal) but it requires to be dynamically resizable and to manage all specific operations like insertions and removals which are not necessary with an immutable array: the dimension is decided when the object is allocated at it is constant.
For normal use there is no noticeable performance difference.
However, If you return an NSArray from a method that internally uses a mutable array for building the response, then I found that a copy of the temporary array can take significant amount of time.
In some instances in DTCoreText I found the [NSMutableArray copy] to NSArray would take 40% of the method time in Instruments. I.e. Returning the mutable array halved the method time.
So when evaluating NSArray versus mutable performance I recommend you direct your attention towards avoiding copying objects. In tight loops or internal methods you should prefer to avoid copying.