ARC forbids autorelease? - iphone

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.

Related

Release Objective C object in C-array with ARC

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.)

Why create a variable rather than direct assignment?

This is a basic question, and I'm not really sure what to search for to see if its been asked before.
In a lot of examples, I've seen property assignments handled like this:
NSArray *tempArray = [/*some code to get array*/];
self.propertyArray = tempArray;
[tempArray release];
Why not just do:
self.propertyArray = [/*some code to get array*/];
What's the difference between the two?
This answer is assuming your not using ARC.
The first code snippet, is the way Apple recommends initializing a property as long as you are doing this in any method besides init. You'll notice Apple code snippets do this a lot. It makes it much easier to manage your memory, and in my opinion it makes it easier to read.
NSArray *tempArray = [[NSArray alloc] initWith....]
self.propertyArray = tempArray;
[tempArray release];
The second code snippet you have could potential lead to a memory leak depending how you set up the NSArray.
This would be a leak. The propertyArray would have an retain count of 2. After you release the instance variable in dealloc, you still have a retain count of 1. That is a leak.
self.propertyArray = [[NSArray alloc] initWith...];
This would be okay, because they both are being autoreleased, which would give you a retain count of 1. As, long as you release the instance variable in dealloc.
// Class Method so autoreleased
self.propertyArray = [NSArray arrayWith....];
// Explicitly declaring autorelease
self.propertyArray = [[[NSArray alloc] initWith.....] autorelease];
It's simply just a matter of preference. I prefer the first way, I think it is easier to to read and follow.
Edit (with ARC):
All these methods would be acceptable with the exception of the release statement and autorelease statement.
[tempArray release];
ARC automatically takes care of the memory management for you, so you do not have to explicitly release them. This is the benefit of ARC, you can create as many objects as you want without the headache of trying to figure out where to release them.
Also, your property would be different. You must either use strong or weak, and not retain. In this case strong would be the solution.
#property (nonatomic, strong) NSArray *tempArray;
In the second example, you don't release the object, which is retained by the property, so you have a memory leak.
self.propertyArray = [[SomeClass alloc] init];
// ^ no release
With ARC, the two statements are equivalent in practice (although you would have to omit the release call for it to actually compile in ARC).
In a manual managed memory scenario, you would leak tempArray in the second ("direct assignment", which it isn't because you're calling a property setter not setting an ivar) example, as you do not have a release call on tempArray to balance it's alloc/init.
The the useful distinction is reduced to expressiveness, the ability to debug, and ultimately the programmers personal preference.
Your first example is the way it was done before the advent of automatic reference counting (ARC). The second example works fine under ARC. Unless you have to do it the old-fashioned way, select ARC for all your projects.
Code like that most likely means that somebody wanted an ability to debug it easier. Basically if you have a separate variable, you can print it out in the debugger without triggering (possibly custom) property setters and getters.

objective-c: when to autorelease an nsnumber object when not using alloc

I noticed that my program was crashing because it was running out of memory. I figured out that this was happening because of this code segment:
DataSet *tempSet = [[DataSet alloc] init];
tempSet.rightFoot = [NSNumber numberWithDouble:temp1];
tempSet.leftFoot = [NSNumber numberWithDouble:temp2];
[footData addObject:tempSet]; //add dataSet object to the array
[tempSet release];
I read some tutorials about memory management online and was able to figure out that I needed to do this: (notice the added "autoreleases")
DataSet *tempSet = [[DataSet alloc] init];
tempSet.rightFoot = [[NSNumber numberWithDouble:temp1] autorelease];
tempSet.leftFoot = [[NSNumber numberWithDouble:temp2] autorelease];
[footData addObject:tempSet]; //add dataSet object to the array
[tempSet release];
I am still confused about why I had to do this. I did not use alloc, new or copy when creating the numberWithDouble.
Does this mean that I would need to add autorelease in this situation as well?:
[subset addObject:[NSNumber numberWithDouble:temp]];
What about this situation?:
tempSet.rightFoot = [NSString stringWithString:#"temp"];
I appreciate any help.
+numberWithDouble
is called a convenience method. Meaning, it replaces the little section of code that would look like this:
[[[NSNumber alloc]initWithDouble:double]autorelease];
Most (if not all) convenience methods are auto release by default, so the OP code with the autoreleases is incorrect, as it drops the retain count to -1.
The equals sign however is equivalent to
[self setRightFoot:[[[NSString alloc]initWithString]autorelease]];
which increments rightFoot's retain count and requires it to be released elsewhere.
as for the -addObject code, it returns void, so it does not in fact increment the receiver's retain count, and requires no release of the receiver. The object in the array should already be released by the convenience method for later, which doesn't matter because the array is now holding "copy" of it.
This is not an answer (I just do not know how to comment -- I only see "share, edit, flag"), but just a few info about Memory Management in iOS:
1. Don't release objects that you do not own.. ---> owned objects are usually the ones you "alloc", "new", "copy." //And probably the one in your #property wherein you "retain" an object.
2. when you "autorelease" an object, don't "release" it afterwards, because that would mean you're releasing the same object twice.
But there's ARC already, so you better upgrade your Xcode to avoid overreleasing objects / memory leaks (for not releasing objects)..
If there's something wrong or inappropriate with the one I put here, please edit. :)

releasing variables to save memory

I have a beginner's question about releasing variables and not wasting memory...
I don't quite understand when to release variables. I understand that I should always do this if I have assigned them in my header file (in my #interface section and my #property commands). I release them in my -(void)dealloc function.
However, what am I supposed to do with variables that I happen to use in some of my methods, e.g.:
for (int temp = 0; temp < 3; temp++) {
// do something...
}
[temp release];
This is obviously wrong (at least xCode tells me so), as 'temp' is undeclared. But why? I've declared it as an int and temp thus takes up space in my memory, I'm sure. How do I tell the program to free up the space temp has taken after I don't need it anymore? I'm sure this is obvious, but I simply don't get it.
I'd be very happy for any suggestions for a beginner of how not to be a memory pig and to have 'memory leaking' everywhere in my apps...
You declared it as an int in the scope of the loop. Once the loop is done, it goes out of scope.
Also, you can not release an int, which is a primitive type. You can only release a subclass of NSObject. A good rule of thumb is that you eventually have to release anything that you called alloc or retain on.
Edit: For your edification, memory management only applies to objects allocated from the heap. That would be NSObjects obtained via "alloc" or must C-level memory allocated with something like "malloc()". Declaring a variable like "int x" is called an "auto" variable in that is is created on the stack and will AUTOmatically disappear then that block ends (the end of a "block" being the end of the function or perhaps the end of a {} pair or even the end of a for/if/while block.
Since Objective-C is basically just a special version of C (with messages), it does not create permanent objects unless you explicitly tell it to. This is different form languages like Python or Javascript.
You only need to release objects, and temp is an int, not an object.
As far as when to release objects, Apple's docs explain that better than I can: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/MemoryMgmt.html
You do only release objects, and not primitive types. For example you create an array with
NSArray *myArray = [[NSArray alloc] init];
This initialization allocated memory which you have to free after your done using your array, it's your responsibility, else there will be memory leaks. You can do that in the dealloc section of a controller, or at the end of a method, or even after you've enumerated through the array and no longer need it.
If you create instances of objects with other methods than alloc, copy or new(rarely used) you have to release them. If you call retain yourself on an object you have to release it as well.
Please refer to apples memory management rules, which have been posted earlier.
There are two ways to store information in RAM in C and c like things, primitives which are allocated automatically by the compiler, and memory chunks allocated by you in your program.
Variables allocated for you by the compiler are called "automatics" and can be marked by the essentially unused (because it is the default) "auto" keyword. Automatics are bound to the scope in which they are declared and go away when it ends. Regular variables, like "int x" are automatic.
Notably, pointers are typically automatic. However, the things they point to are not. Those would be the thing you asked to be allocated.
In objective-c, things are allocated with the alloc message. However, sometimes a class will call this for you, so you might not see it. To help make it clear what you should do, there is a tradition: If you get an object where you alloc'ed it, got it from a class method with the word "copy" in the method name, or sent it a "retain" message, then you own a share of it, and it won't go away until you send it a release message.
If you didn't get the object through one of those means, you must not release it, because you don't have a share in it.
So, in summary: regular variables (int, short, char, double, float, long) are automatic, no need to allocate it. Pointers are also automatic, however, the things they are pointing to are not. In obj-c, you own a share if you alloc'ed it, copy'ed it, or sent it a retain message.
You can't release an integer...
Release works only with instance of Objective-C classes.
Variables such as integers are placed on the stack, and they does not persist after a function/method call, unless allocated explicitely.
You only release objects. If you use the alloc, init procedure to create an object you must release it. If you retain an object you must release it. If you use a method that has the word "create" in it, you must release it. Anything else, the system will handle for you.
Primitives do not need to be released, only objects.
Biggest thing to keep in mind is that whenever you "alloc" or "retain" an object, put a corresponding "release" or "autorelease".
you see an error on the line [temp release]; because temp is not in scope. temp will not be seen outside of the for loop you created.
you do not need to clean up the memory of temp, since you have not claimed ownership of it(see Memory Management Rules): http://developer.apple.com/library/ios/#documentation/general/conceptual/DevPedia-CocoaCore/MemoryManagement.html
examples of objects where you do not need to release/manage memory:
NSArray *myArray = [NSArray array];
NSNumber *myNumber = [NSNumber numberWithInt:5];
NSString *myString = #"Hello World";
NSInteger i = 5;
int x = 2;
examples of objects where you do need to release/manage memory:
NSArray *myArray = [[NSArray alloc] initWithObjects:#"Hello", #"World", nil];
NSNumber *myNumber = [[NSNumber alloc] initWithInt:5];
NSString *myString = [[NSString alloc] initWithString:#"Hello World"];
-
typically, when your completely done using an object you own, you clean up its memory
see apple's docs for explanations on properties: http://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/ObjectiveC/Chapters/ocProperties.html#//apple_ref/doc/uid/TP30001163-CH17-SW1
setting a property with assign or readonly: you should not worry about releasing its memory, as you don't own it
property with retain or copy: you claim ownership of the object and need to release it at some point
this answer won't answer/solve all memory management questions/concerns, but it may shove you in the right direction

Why should a self-implemented getter retain and autorelease the returned object?

Example:
- (NSString*) title {
return [[title retain] autorelease];
}
The setter actually retained it already, right? and actually nobody should bypass the Setter... so I wonder why the getter not just returns the object? It's actually retained already. Or would this just be needed in case that in the mean time another objects gets passed to the setter?
From here http://www.macosxguru.net/article.php?story=20030713184140267
- (id)getMyInstance
{
return myInstanceVar ;
}
or
- (id)getMyInstance
{
return [[myInstanceVar retain] autorelease] ;
}
What's the difference ?
The second one allows the caller to get an instance variable of a container object, dispose of the container and continue to play with the instance variable until the next release of the current autoreleased pool, without being hurt by the release of the instance variable indirectly generated by the release of its container:
aLocalVar = [aContainer getAnInstanceVar] ;
[aContainer release];
doSomething(aLocalVar);
If the "get" is implemented in the first form, you should write:
aLocalVar = [[aContainer getAnInstanceVar] retain];
[aContainer release];
doSomething(aLocalVar);
[aLovalVar release];
The first form is a little bit more efficent in term of code execution speed.
However, if you are writing frameworks to be used by others, maybe the second version should be recommanded: it makes life a little bit easier to people using your framework: they don't have to think too much about what they are doing…;)
If you choose the first style version, state it clearly in your documentation… Whatever way you will be choosing, remember that changing from version 1 to version 2 is save for client code, when going back from version 2 to version 1 will break existing client code…
It's not just for cases where someone releases the container, since in that case it's more obvious that they should retain the object themselves. Consider this code:
NSString* newValue = #"new";
NSString* oldValue = [foo someStringValue];
[foo setSomeStringValue:newValue];
// Go on to do something with oldValue
This looks reasonable, but if neither the setter nor the getter uses autorelease the "Go on to do something" part will likely crash, because oldValue has now been deallocated (assuming nobody else had retained it). You usually want to use Technique 1 or Technique 2 from Apple's accessor method examples so code like the above will work as most people will expect.
Compare this code
return [[title retain] release]; // releases immediately
with this
return [[title retain] autorelease]; // releases at end of current run loop (or if autorelease pool is drained earlier)
The second one guarantees that a client will have a non-dealloced object to work with.
This can be useful in a situation like this (client code):
NSString *thing = [obj title];
[obj setTitle:nil]; // here you could hit retainCount 0!
NSLog(#"Length %d", [thing length]); // here thing might be dealloced already!
The retain (and use of autorelease instead of release) in your title method prevents this code from blowing up. The autoreleased object will not have its release method called until AFTER the current call stack is done executing (end of the current run loop). This gives all client code in the call stack a chance to use this object without worrying about it getting dealloc'ed.
The Important Thing To Remember: This ain't Java, Ruby or PHP. Just because you have a reference to an object in yer [sic] variable does NOT ensure that you won't get it dealloc'ed from under you. You have to retain it, but then you'd have to remember to release it. Autorelease lets you avoid this. You should always use autorelease unless you're dealing with properties or loops with many iterations (and probably not even then unless a problem occurs).
I haven't seen this pattern before, but it seems fairly pointless to me. I guess the intent is to keep the returned value safe if the client code calls "release" on the parent object. It doesn't really hurt anything, but I doubt that situation comes up all that often in well-designed libraries.
Ah, ok. from the documentation smorgan linked to, it seems this is now one of the methods that Apple is currently recommending that people use. I think I still prefer the old-school version:
- (NSString *) value
{
return myValue;
}
- (void) setValue: (NSString *) newValue
{
if (newValue != myValue)
{
[myValue autorelease]; // actually, I nearly always use 'release' here
myValue = [newValue retain];
}
}