Release Objective C object in C-array with ARC - iphone

I don't know how to release an Objective-C object that I have stored in an old-fashioned c-array.
(Remark: While writing this after much searching, I think I found a bug in the test-code so this seems to be a solution rather than a question. Well, I've spent a lot of time on it so I'll post it anyway...)
I'd like to convert older code to ARC, because I am spending too much time on debugging memory-management related bugs (sorry---the retain/release rules simply aren't hardwired in my spine, and it takes me literally hours to find a missing retain, because the errors pop up at unrelated moments, probably during or after memory cleanup).
So I have some existing code with c-style arrays (say a two-dimensional array of UILabel*'s), where I can happily calloc() the pointers and access them through some array[col*colstride+row*rowstride], where array is of the type UILabel **; Let's assume the UILabel*s are filled at random order, so I can't use an NSMutableArray for that.
Now in ARC, the compiler wants me to make the type of array to be UILabel *__strong*, it seems (some people write that as __strong UILabel **).
What I don't understand is how I can tell ARC to release the UILabel objects when it is time to do so (say in the dealloc() of my object that uses the c-array). In trying to understand the problem, I have a small set of objects, Memory and MemoryUnit, the former trying to store a large c-array of the latter.
-(Memory*)init {
self = [super init];
if (self) {
MemoryUnit * unit = [[MemoryUnit alloc] init];
array = (__strong id *) calloc(sizeof(MemoryUnit*), 1024);
array[0] = unit;
}
return self;
}
-(void)dealloc {
for (int i=0; i<1024; i++) array[i]=nil;
free(array);
}
In MemoryUnit we have the objects to be stored in the c-array (so this MemoryUnit is in the place of the UILabel mentioned above). For testing I had the code
-(void)dealloc {
NSLog(#"removed %x", (int)self);
}
in its dealloc() for debugging.

As Bryan said, we need an answer in the stack overflow system.
So I do:
Solution
Apparently, setting the array element of type MemoryUnit *__strong to nil causes the object to be released, as if this element had been declared in a #propetty and #synthesize pair of statements. This is actually suggested in C-style array of pointers to Objective-C objects under ARC I think
(I found the documentation in XCode very terse, and the ARC compiler definitions only told me what was not allowed rather than giving a hint on how to do things correctly.)

Related

ARC forbids autorelease?

New to ios and trying to return an NSString from an function. As I understand, I need to [NSString... alloc] init] in order to create the string for return. Also, since I called alloc, I guess I have to autorelease the object myself however I'm getting the message "ARC forbids explicit message send of 'autorelease'" so.. how do I tell ios when I'm done with that allocated NSString?
- (NSString *) generateUID
{
char foo[32];
// create buffer of all capital psuedo-random letters
for (int i = 0; i < sizeof(foo); i++)
foo[i] = (random() % 25) + 65; // 0-25 + CAPITAL_A
NSString *uid = [[NSString alloc] initWithBytes:foo length:sizeof(foo) encoding:NSASCIIStringEncoding];
NSLog (#"uid: %#", uid);
return (uid);
}
ARC = automatic reference counting = the compiler adds the necessary releases and autorelases based on its analysis of your code. You don't see this of course because it happens behind the scenes. As mentioned by sosbom in his comment, you really should read the applicable documentation on the Apple website.
You don't.
autorelease is just there for compatibilities sake, prior to iOS 5, you'd have to do:
Thing *myThing = [[Thing alloc] init]; // Retain count: 1
[myArray addObject:myThing]; // Retain count: 2
[myThing release]; // Retain count: 1
With the above code, the responsability of holding the object is given to the array, when the array gets deleted, it will release its objects.
Or in the case of autorelease.
- (MyThing*)myMethod
{
return [[[MyThing alloc] init] autorelease];
}
Then it would release the object once it gets to a NSAutoReleasePool and get removed once drained.
ARC takes care of that now, it pretty much inserts the missing pieces for you, so you don't have to worry about it, and the beauty of it, is that you get the advantages of reference counting (vs garbage collector), at the cost of an increased compile-time checking to do the ARC step, but your end users don't care about compile-time.
Add to that, that you now have strong and weak (vs their non-ARC siblings retain and assign, the later one still useful for non-retained things), and you get a nice programming experience without tracing the code with your eyes and counting the retain count on your left hand.
Short answer is you don't! ARC will handle the memory management for you.
When ARC is turned on, the compiler will insert the appropriate memory management statements such as retain and release messages.
It is best to use ARC as the compiler has a better idea of an object's life cycle and is less prone to human error.
One other important thing to note about ARC. ARC is not the same as traditional garbage collection. There is no separate process or thread running in the background, like java's GC, which deletes objects when there is no longer a reference to them. One could view ARC as compile time garbage collection :).
The only other thing to be aware of is reference cycles and bridging pointers/objects between Objective-C and Obj-C++/C. You might want to look-up http://en.wikipedia.org/wiki/Weak_reference
Hope this helps
In general, you should define a constructor method in your class and put the alloc logic in that method. Then, it is much harder to make a type casting error as the alloc/init approach always return (id) and it is not very type safe. This what built-in classes like NSString do, like [NSString stringWithString:#"foo"], for example. Here is a nice little block you can use to write code that works both with older non-arc compilation and with arc enabled.
+ (AVOfflineComposition*) aVOfflineComposition
{
AVOfflineComposition *obj = [[AVOfflineComposition alloc] init];
#if __has_feature(objc_arc)
return obj;
#else
return [obj autorelease];
#endif // objc_arc
}
You then declare the method and create an instance of the object like so:
AVOfflineComposition *obj = [AVOfflineComposition aVOfflineComposition];
Using the above approach is best, as it is type safe and the same code with with arc vs non-arc. The compiler will complain if you attempt to assign the returned object to a variable of another type.

Does passing an object as a parameter for a method increment its retain counter under ARC? [duplicate]

When compiling with ARC, method arguments often appear to be retained at the beginning of the method and released at the end. This retain/release pair seems superfluous, and contradicts the idea that ARC "produces the code you would have written anyway". Nobody in those dark, pre-ARC days performed an extra retain/release on all method arguments just to be on the safe side, did they?
Consider:
#interface Test : NSObject
#end
#implementation Test
- (void)testARC:(NSString *)s
{
[s length]; // no extra retain/release here.
}
- (void)testARC2:(NSString *)s
{
// ARC inserts [s retain]
[s length];
[s length];
// ARC inserts [s release]
}
- (void)testARC3:(__unsafe_unretained NSString *)s
{
// no retain -- we used __unsafe_unretained
[s length];
[s length];
// no release -- we used __unsafe_unretained
}
#end
When compiled with Xcode 4.3.2 in release mode, the assembly (such that I'm able to understand it) contained calls to objc_retain and objc_release at the start and end of the second method. What's going on?
This is not a huge problem, but this extra retain/release traffic does show up when using Instruments to profile performance-sensitive code. It seems you can decorate method arguments with __unsafe_unretained to avoid this extra retain/release, as I've done in the third example, but doing so feels quite disgusting.
See this reply from the Objc-language mailing list:
When the compiler doesn't know anything about the
memory management behavior of a function or method (and this happens a
lot), then the compiler must assume:
1) That the function or method might completely rearrange or replace
the entire object graph of the application (it probably won't, but it
could). 2) That the caller might be manual reference counted code, and
therefore the lifetime of passed in parameters is not realistically
knowable.
Given #1 and #2; and given that ARC must never allow an object to be
prematurely deallocated, then these two assumptions force the compiler
to retain passed in objects more often than not.
I think that the main problem is that your method’s body might lead to the arguments being released, so that ARC has to act defensively and retain them:
- (void) processItems
{
[self setItems:[NSArray arrayWithObject:[NSNumber numberWithInt:0]]];
[self doSomethingSillyWith:[items lastObject]];
}
- (void) doSomethingSillyWith: (id) foo
{
[self setItems:nil];
NSLog(#"%#", foo); // if ARC did not retain foo, you could be in trouble
}
That might also be the reason that you don’t see the extra retain when there’s just a single call in your method.
Passing as a parameter does not, in general, increase the retain count. However, if you're passing it to something like NSThread, it is specifically documented that it will retain the parameter for the new thread.
So without an example of how you're intending to start this new thread, I can't give a definitive answer. In general, though, you should be fine.
Even the answer of soul is correct, it is a bit deeper than it should be:
It is retained, because the passed reference is assigned to a strong variable, the parameter variable. This and only this is the reason for the retain/release pair. (Set the parameter var to __weak and what happens?)
One could optimize it away? It would be like optimizing every retain/release pairs on local variables away, because parameters are local variables. This can be done, if the compiler understands the hole code inside the method including all messages sent and functions calls. This can be applied that rarely that clang even does not try to do it. (Imagine that the arg points to a person (only) belonging to a group and the group is dealloc'd: the person would be dealloc'd, too.)
And yes, not to retain args in MRC was a kind of dangerous, but typically developers know their code that good, that they optimized the retain/release away without thinking about it.
It will not increment behind the scenes. Under ARC if the object is Strong it will simply remain alive until there are no more strong pointers to it. But this really has nothing to do with the object being passed as a parameter or not.

Difference between self.ivar and ivar?

aclass.h
#interface aClass : NSObject {
NSString *name;
}
#property (nonatomic, retain) IBOutlet NSString *name;
#end
aclass.m
#implementation aClass
#synthesize name;
- (void)dealloc {
[name release];
[super dealloc];
}
- (void)test1 {
name = #"hello";
}
- (void)test2 {
self.name = #"hello";
}
Take above as an example. Could someone please explain the difference between name = #"hello" and self.name = #"hello"? Thanks!
EDIT: Follow-up question: How to write my own setter for an ivar, i.e.: self.ivar = ...?
BE AWARE, THIS POST IS OLD !
This post is from the previous decade.
Be sure to read the important footnote down below, cheers!!
It's really difficult to understand all this, when you're just getting started.
Here are some SIMPLE, PRACTICAL rules of thumb FOR BEGINNERS.
To repeat, this post is FOR BEGINNERS.
The aim here is to allow you to quickly move from the starting line, to being able to confidently use the system in most situations.
Later, you can really learn about the inner workings of these issues.
(1) Don't ever say name=#"hello". Always say self.name=#"hello". Do a project-wide search for name and ensure you always say self.name and not name, when you set it or change it.
(2) You know all that infuriating stuff about memory management, initialising, releasing and so on. If you use the self thingy, it takes care of all that for you. Cool huh?
(3) The self thingy is particularly useful because you can easily "change" the string (or whatever it is) as you go along. So, it's totally OK to do this,
self.name=#"aa";
self.name=#"bb";
self.name=#"cc";
whereas (in a word) you can never, ever, for any reason, do this...
name=#"aa";
name=#"bb";
name=#"cc";
( * ) Regarding your literal question, "please explain the difference between name = #"hello" and self.name = #"hello"?" This is easy to do.
The first one is just setting a variable. You know, exactly like "x=42" in the old days when life was simple and we were 13 years old.
The second one is completely different, specifically it is calling a complicated routine (known as "the setter") to do a whole lot of amazing and astonishing stuff for you.
So that is the literal answer to your question. The first one just sets the variable (and don't forget, there are a whole lot of pointers and other weird stuff involved, and as a rule you certainly can not just set pointers willy-nilly like that). The second one actually calls a big complicated routine and hence does a whole lot of stuff for you.
Once again, the second one is exactly like saying...
[name bigComplicatedRoutineHere:#"hello"];
...it is very helpful to always remember that the syntax self. ... is literally calling a routine.
Indeed, some thinkers on the topic thought it was a dumb idea when they introduced this self.X syntax to mean [X complicatedThingHere]. It introudces a lot of confusion, and every beginner asks exactly what you are asking.
Personally, it took me over nine years to get this clear in my head. :-) So again, I emphasise that you must remember that when you say self.x, in fact, you are actually calling a routine.
To repeat: the "self dot" syntax in fact calls a routine. (Indeed I believe one of the preprocessors simply expands it to [x amazingStuffHere]. )
I have tried to answer in a way that will keep you going and allow you to advance and use more features, while you learn about memory management, properties, and so on. If you are more advanced than this post, just ignore it.
Please note that this post is meant to be advice for beginners to enable them to keep going and not get infuriated. Hope it helps!
2014 update! Important Note on ARC for beginners ...
Note, this post is five years old now! It's been read by thousands of beginners and there have been many followup questions etc. Please note that, today in the new "ARC world". To some extent: if you're a beginner: you should pretty much only use!! properties. ie, use "self.whatever" at all times, everywhere. In any event, just be aware that the information in this post is "largely historic" and is becoming more so every day. Of course, it goes without saying that once you are an expert, you will need to and will understand every subtle detail of all this. Hope it helps someone.
self.name uses the accessor and/or mutator defined by you (this is nonatomic and retain in your case). So when you call self.name = foo, it will call the setName:(NSString *)str mutator generated by the compiler, which will first release the current string, then retains the new string and finally sets name to the retained string.
Just calling name = foo does nothing more than assigning name to foo.
This also means that you can only call self.xxx when you have defined a property for the ivar, otherwise the compiler will tell you that it doesn't know about it(iVar).
name = #"Joe"
You're accessing directly the variable, bypassing the getter method that Cocoa took the trouble of creating for you. Usually, not the wisest thing to do.
self.name = #"Joe"
Now your going through the method you asked cocoa to create for you. This is usually the best way.
As a rule of thumb, use always the setter and getter provided by Cocoa, with ONE exception: dealloc. In dealloc, you should always release the variable directly, not through the getter method:
-(void) dealloc {
[name release]; // instead of [[self name] release]
...
[super dealloc];
}
The reason to avoid accessors in dealloc is that if there are observers or an override in a subclass that triggers behavior, it'll be triggered from dealloc which is pretty much never what you want (because the state of the object will be inconsistent).
OTOH, there's also a slightly more convenient syntax for declaring iVars that you might not be aware of. If you are only targeting 64bit macs, You can use properties to generate both accessor methods and the instance variable itself:
#import <Cocoa/Cocoa.h>
#interface Photo : NSObject
#property (retain) NSString* caption;
#property (retain) NSString* photographer;
#end
It's real a memory management, firt the property grammar is real setter and getter method, when use self.xxx = ?, it could call setter method, the object retain cout +1, name can not be release, however if name = foo is nothing about property grammar.
setter method example:
-(void)setObj:(ClassX*) value
{
if (obj != value)
{
[obj release];
obj = [value retain];
}
}

NSMutable Array and brain damage

I have understandably attracted some smart ass answers to some bone head questions I have asked lately due to my complete misunderstanding of obj c and NSMutable arrays. So I've looked in a book I have and Google and it would appear that may be I shouldn't program because I'm still stuck.
Say I'm looping through method A and each loop through I want to add a double into a NSMutable array. This is what I've discovered so far.
You can't put primitives in arrays, so I made my double into a NSNumber object
NSNumber *newObject = [NSNumber initWithDouble:doubleNumber];
XCode warns: 'NSNumber' may not respond to '+initWithDouble:'
and when I compile it get:
Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '+[NSNumber initWithDouble:]: unrecognized selector sent to class 0x1ffea0'
I ignore that and forge on. Some one told me I need an init method for the array, which makes sense because I don't want that happening in the loop. This is my init method:
-(id) init{
[super init];
arrayOfTouches = [[NSMutableArray alloc] init];
return self;
}
I haven't got to try to add it to the array yet.
[arrayOfTouches addObject:newObject];
Will this work to print out the array.
NSLog(#"array: %#", touchBeginObj);
Bonehead questions, probably. But damn if I can find anything that has all the pieces about what you can and can't do with an good example.
Thanks for any help or smart ass comments.
Yes, I have a Obj-C book, 3 actually and yes I'm reading them :)
Have a good weekend.
NSNumber *newObject = [NSNumber initWithDouble:doubleNumber];
You’re missing the +alloc call in the above code, which is why it’s throwing that error—but why not just use:
NSNumber *newObject = [NSNumber numberWithDouble:doubleNumber];
It’s autoreleased, so you don’t have to worry about releasing it later.
I’m not sure what either of the other questions are asking, could you possibly rephrase them? From the code you’ve given, I think it should work
First :
[NSNumber numberWithDouble: double]
instead of
[NSNumber initWithDouble: double]
Your addObject looks fine.
You have several ways to print your array, I'd suggest iterating, as it will be useful later:
for (NSNumber *number in arrayOfTouches)
{
NSLog(#"Number %f", [number doubleValue]);
}
initWithDouble is an instance method, you're looking for the class method numberWithDouble.
Change this:
NSNumber *newObject = [NSNumber initWithDouble:doubleNumber];
to this:
NSNumber *newObject = [NSNumber numberWithDouble:doubleNumber];
-initWithDouble is an instance method of NSNumber (so you would need to do [NSNumber alloc] first). +numberWithDouble is a class method.
You need to have zero warnings from the compiler - you can't ignore them and 'forge on'.
You are struggling with the basics, do you have experience of other programming languages?
There are a few things you must know in order to code in Objective-c and you must be familiar with the general concepts of object-oriented programming. Also a little C can be helpful as objective-c is an extension to C and it can give some perspective as to why object orientation is so useful and worth-the-effort.
If you already know a language like Python, Java, or even Actionscript then pretty much all of the concepts are the same and objective-c really isn't that difficult. You just need the specifics on how those concepts translate into objective-c. For example,
How do you define a class? How do you override an existing class? What does an initializer method look like? How do you create an instance of a class? etc. There are a few more things than this, but really not that many - you need to learn them, or at least have references at hand in the beginning so you don't go wrong. If you don't know what they mean then you need to learn that.
A 'Class' is like a blueprint for the layout of a piece of memory, in the case of NSNumber a piece of memory that we would hope is going to hold a number. The NSNumber Class knows how big the memory has to be and how it should be laid out. We really care little about the blueprint, the Class - we want an actual chunk of memory that can hold a number - an instance of the Class.
In objective-c creating an object, an instance, of a given class always, everytime, always, always involves -- firstly -- claiming ownership of a free chunk of memory with the correct size, saving the address of that chunk of memory to a variable, then giving the object a chance to do it's own initial setup by calling it's preferred setup method.
To claim ownership of the memory you send the alloc method to the class.
NSNumber *myNumberVariable = [NSNumber alloc];
To set the number up with the initial value of 10.0 you send the message initWithDouble: to your new instance.
[myNumberVariable initWithDouble:10.0];
For convenience these can be, and usually are combined into one statement.
NSNumber *myNumberVariable = [[NSNumber alloc] initWithDouble:10.0];
This is the most fundamental aspect of objective-c programming. You cannot do anything without thoroughly understanding this. Googling init objective-c returns literally hundreds of tutorials, guides, cheat-sheets and help.
If your own Class needs a property initializing when an instance is created, like your arrayOfTouches, you must override the preferred setup method of the parent Class. If the parent Class is NSObject, NSObject's preferred setup method is init. If you create an object in your setup method you must always have a dealloc method. This will always, always, all of the time look like this:
- (id)init {
self = [super init];
if(self){
}
return self;
}
- (void)dealloc {
[super dealloc];
}
Only the name "init" will change, depending on the name of the method you are overriding, - (id)init becomes - (id)nameOfMethodIAmOverriding and [super init] becomes [super nameOfMethodIAmOverriding];
Given this standard template for setup and teardown you can add in the setup and teardown of your own properties. In your case giving you.
- (id)init {
self = [super init];
if(self){
arrayOfTouches = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc {
[arrayOfTouches release];
[super dealloc];
}
Look, it's not that i think you have Boneheaded questions, they are sensible questions but if you have 3 books - the answers are almost certainly on the first few pages of each book - maybe you are going about learning this wrong. Somehow you are not getting the fundamentals. The best i can suggest is to go more slowly and do the exercises in the book, Or choose a simpler language and attempt to master that before moving to objective-c.
Go to Help-->Developer Documentation
Search for NSNumber. Under class methods you'll find how to create a NSNumber with a double.

There's got to be an easier way of dealing with arrays!

To optimize a bottleneck, I converted the creation of a large NSArray to a c-style array. (The resulting creation was 1/8 the time of the original NSArray version. Yeah!) But once it's created, speed is no longer an issue, so I'd rather benefit from it being an NSArray again.
However, it seems ridiculously involved to convert a c-style array to an NSArray (unless I'm missing some magic initWithArrayWrapElementsInObjects method.)
As I understand the process now, I first have to create an NSMutableArray, iterate through the c-style array converting each element (floats in my case) to objects, adding each object to the NSMutableArray, then creating the NSArray with the NSMutableArray.
Is that right? There's got to be a better way.
And help would be appreciated.
Thanks!
There's no direct way to take a blob of memory that you own and "convert" it cheaply into an NSArray-- after all, the framework would need to then own that memory, and it doesn't know where you got it from (malloc, stack, etc). If there were a convenience method for initWithArrayWrapElementsInObjects, it would itself need to do internally what you surmise: iterate over your provided memory and add items to itself (it's possibly the framework could do this as quickly as a memcpy, but who knows).
One way you could tackle this (and probably a fun learning exercise) is by actually creating your own subclass of NSArray that manages memory exactly as you want (ie, lets you create and init with whatever semantics you want), but that behaves to the outside world as an NSArray would. You can do this by inheriting from NSArray and implementing the methods count: and objectAtIndex: to operate on whatever memory you're holding on to. Obviously, you'd need to implement the management of your own memory in the init/dealloc, etc methods as well. See this page http://developer.apple.com/mac/library/documentation/Cocoa/Reference/Foundation/Classes/NSArray_Class/NSArray.html
under "Subclassing Notes".
The design discussion here hinges on what your data looks like. NSArray, of course, expects its items to be Obj-C references (of type id), and not just arbitrary chunks of data. If your C-style array is holding structures or some other primitive values that aren't object references, then this technique won't really work for you-- NSArray's interface will never be happy with non-reference items.
One final note: you mention taking an NSMutableArray and "creating" an NSArray with it. You should be aware that an NSMutableArray is already an NSArray, since it's a subclass. You can use an instance of NSMutableArray anywhere you'd want an NSArray, without creating some new copy of it.
UPDATE: Missed the note about your array containing floats. Yeah, you're a little bit screwed here. NSArrays want objects. If the capacity doubling was the expensive part (as another poster notes), then try initWithCapacity:. If it's the boxing/unboxing of the floats into object types, there's nothing you can do.
I have created (but don't have handy) a pair of very simple classes (called like MYArray and MYMutableArray) that are intended to wrap just this kind of data with NSArray-like methods on them. But they're not interchangeable with NSArrays. You must use them intentionally.
UPDATE #2. I know it's been ages since this question was live, but I just revisited it and realized there actually is a sort of clever way around this in this specific case. (You want a non-mutable NSArray from a C-style float array). You can create a custom subclass of NSArray that wraps the float values and only converts them to objects when they're accessed via the primitives. This may have performance pitfalls in some corners (?), but it does neatly meet your requirements:
#interface FloatProxyArray : NSArray
{
float * values;
NSUInteger count;
}
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues;
#end
.
#implementation FloatProxyArray
- (id)initWithCArray:(float *)arrayOfFloats count:(int)numberOfValues
{
if ((self = [super init])) {
values = (float *)malloc(numberOfValues * sizeof(float));
if (!values) {
[self release]; return nil;
}
memcpy(values, arrayOfFloats, numberOfValues * sizeof(float));
count = numberOfValues;
}
return self;
}
- (void)dealloc
{
free(values);
[super dealloc]
}
- (NSUInteger)count
{
return count;
}
- (id)objectAtIndex:(NSUInteger)index
{
if (index >= count) {
[NSException raise:NSRangeException format:#""];
return nil;
}
float val = values[index];
return [NSNumber numberWithFloat:val];
}
#end
(N.B. Written in the editor without compiling/testing.)
One optimization that you can do with the NSMutableArray is initWithCapacity which will prevent the doubling of your array which is the expensive operation in the addition.
Outside of that, since NSArrays and NSMutableArrays expect objects, so it's difficult to get around this.
What benefits of it being an NSArray are you looking to get?
It seems like you may be better off with a custom wrapper object around the C array that responds to whatever NSArray messages you are looking to call. Otherwise you are right back at the point of array creation... You could try manually creating a call to initWithObjects, but at the very least every float has to be wrapped in an NSNumber which would bring down your speed again.
If you really need an NSArray because something else you want to use takes NSArray objects, then you are probably better off subclassing NSArray (following the guidelines posted by Ben).
The “best” optimisation (for speed) would almost certainly be to avoid using NSArray altogether, if possible.