Objective C ARC equivalent for self? - iphone

What is the equivalent keyword i can use in the place of self in ARC enabled projects?
ex:- [self mymethod]; what is ARC equivalent of this method call?

I don't quite get it? Why ARC should have different syntax for method calls? It is an automatic memory management, where in most cases you won't need to use retain/release, nothing more. So it would look like this:
[self mymethod];

In ARC(Automatic Reference Counting),you don't need to release or retain. It has nothing to do with calling methods!
ARC - Automatic Reference Counting implements automatic memory management for Objective-C objects and blocks, freeing the programmer from the need explicitly insert retains and releases. Since this is handled at compile time, no collector process is need to continually clear memory and remove unreferenced objects.
For calling a method, you still do it this way:[self mymethod];

it's still the same
[self myMethod];
But in ARC environment, IIRC, you need to do it like this: (I don't know if this is the source of your question, but when I migrated the first time to ARC, I get compile error if I'm not doing this).
#interface myController()
- (void)myMethod; // you need to declare the method here, if you haven't declared it on the .h
#end
#implementation
- (void)viewDidLoad
{
[super viewDidLoad];
[self myMethod];
}
- (void)myMethod
{
NSLog(#"!");
}
#end
hope this help

Related

confused by ARC

The codes below I used on Xcode 3.2 and worked very well
#interface MoObject : UIViewController
{
NSMutableArray *categoryArray;
}
#property (nonatomic, retain) NSMutableArray *categoryArray;
#end;
#implementation MyObject
#synthesize categoryArray;
- (void)viewDidLoad
{
[super viewDidLoad];
NSMutableArray *a = [[NSMutableArray alloc] init];
categoryArray = a;
[a release]; //AAA:I can not release this, it does not report compiling error , but after some operation, it will cause exec bad error
}
- (void)dealloc {
[category release];
[super dealloc];
}
I just move to Xcode 4.3.1 iOS 5.1
the same function causes so many exec bad error.
Even I close the ARC of whole project.
The problem still exist, it looks like I can not release the object array at point AAA
Welcome any comment
The point of ARC is that it handles the retain/release code for you. Since your array "a" is declared locally, when that function ends, ARC will insert the code release it for you. Same for dealloc - you don't need it with ARC (and actually can't use it).
But if you don't like or want to learn ARC you don't have to use it. It's an option when you create a new project.
You are not using ARC. If you were, code using -release would not even compile. Neither would calling [super dealloc] in your -dealloc method.
What you have is just an ordinary memory management bug. You are assigning a directly to the instance variable categoryArray. You are not using the setter which is synthesized for the property and it is the setter which does the proper memory management. Therefor, categoryArray ends up pointing to a deallocated object. If you were to use either self.categoryArray = a or [self setCategoryArray:a], which are equivalent statements, then your bug would go away.
Under ARC, this bug would be mostly hidden. The categoryArray instance variable would by default be __strong, so the array would be retained at least as long as categoryArray pointed to it and you wouldn't get EXC_BAD_ACCESS errors. However, it's still buggy to directly assign to it, bypassing the setter, except within initializer methods.

ARC and releasing memory

I have read many articles online, and I am a bit confused about ARC. I will list my questions below, please help me answer them.
1.) What does the keyword strong do (in #property (nonatomic, strong) …)?
2.) Don't we have to release or autorelease what we alloc anymore, because I get a warning saying that I need not have to. (I am not at my Mac, so I can't copy the warning I got.)
3.) I couldn't find the Leaks tool in Xcode 4.2. Where did it go? Or don't we have to check for leaks anymore?
4.) When creating the project using Xcode 4.2, I clicked on "enable ARC", so will my program work on iOS 3? (I think ARC only supports iOS 4 and above.)
strong is an ARC analog to retain (there's no retain under ARC). It means that property value will be hold by class where the #property was defined, and released upon reassignment or dealloc. (Note that under ARC there's no need to release or nullify properties in dealloc).
The point of ARC is taking care of retain/release routine by compiler, so there's no need for manual memory management methods.
You can check for leaks by running Profile (Product -> Profile menu) and selecting Leaks instrument. Leaks can be introduced with cyclic references or in CoreFoundation code (ARC doesn't work with CoreFoundation). Also if you are mixing ARC and non-ARC code, the latter could be a source of leaks.
ARC is supported by OS starting from iOS 4.0 (though iOS 5 SDK is needed). The key difference between 4.0 and 5.0 ARC support is availability of weak property specifier. Weak property (__weak variable) will be automatically nullified when the strong value it refers to is released. There are no weak properties in 4.0, so __unsafe_unretained specifier should be used (It's a close analog to assign specifier, it doesn't retain value and can point to already deallocated value, so it's dangerous).
Here's a great explanation of ARC:
Everything you need to know about automatic reference counting
Strong is equivalent to retain in ARC. It indicates ownership: What does the "strong" keyword do
No, that's done for you. ARC inserts those statements in (compiled) code automatically. That's its main job. But, per Abizern's comment, this only works for your objects and Cocoa objects. If you're using Core Foundation (CF*) classes then you must read about the __bridge family of casts. You might start reading here.
It's in Instruments. Per iHunter's answer, Cmd+I or Product->Profile, then choose Leaks. Particularly important given (2).
It will not work.
Well, there are already three answers that cover the main things so I'll focus on a single detail here, that isn't already mentioned:
3.) I couldn't find the Leaks tool in Xcode 4.2. Where did it go? Or don't we have to check for leaks anymore?
Yes we do still need to check for leaks:
ARC is not garbage collection, it is automated retain/release.
Thus, it is still possible — in fact, it's pretty easy — to create leaks!
Consider the following example:
#class Puppet;
#protocol PuppetDelegate : <NSObject>
- (void)puppetDidTwistStrings:(Puppet *)puppet;
#end
#interface Puppet : NSObject {
id <PuppetDelegate> delegate_;
}
- (id)initWithPuppetDelegate:(id <PuppetDelegate>)delegate;
- (void)unravelStrings;
#end
#implementation Puppet
- (id)initWithPuppetDelegate:delegate
{
if (!(self = [super init])) return nil;
delegate_ = delegate;
return self;
}
// assume some implementation for unravel strings
#end
#interface MasterOfPuppets : NSObject <PuppetDelegate> {
NSMutableArray *puppets_;
}
- (void)puppetDidTwistStrings:(Puppet *)puppet;
- (void)bringOutAPuppet;
#end
#implementation
- (id)init
{
if (!(self = [super init])) return nil;
puppets_ = [[NSMutableArray alloc] init];
return self;
}
- (void)bringOutAPuppet
{
Puppet *newPuppet = [[Puppet alloc] initWithPuppetDelegate:self];
[puppets_ addObject:newPuppet];
}
- (void)puppetDidTwistStrings:(Puppet *)puppet
{
BOOL isOurPuppet = [puppets_ containsObject:puppet];
if (!isOurPuppet) return;
[puppet unravelStrings];
}
#end
This example is (admittedly) a little stupid, but this code will leak, and ARC is not going to help you about it, whereas garbage collection would:
A MasterOfPuppets can have many puppets, which he stores in an instance variable — so far so good.
A Puppet has a delegate which it is going to inform if its strings are entangled — and here it starts.
Whereas in non-ARC code an instance variable was simply a pointer that was being assigned to, ARC assumes that if you stash something in a variable, you want to cling on to it and it will retain the value unless you tell it not to.
So you have a classical retain-cycle here and ARC won't save you from those.
This may seem a contrived and far-fetched example, but it's not: I've seen this quite a bit in delegate relationships.
(The solution, by the way, is pretty simple: declare Puppet's delegate_ instance variable as weak and everything works as it should.)

Releasing ivars in Objective-C

OK, looking at this:
Apple docs: Declared Properties
If you scroll down to dealloc it reads:
"Typically in a dealloc method you should release object instance variables directly (rather than invoking a set accessor and passing nil as the parameter), as illustrated in this example:"
- (void)dealloc {
[property release];
[super dealloc];
}
"If you are using the modern runtime and synthesizing the instance variable, however, you cannot access the instance variable directly, so you must invoke the accessor method:"
- (void)dealloc {
[self setProperty:nil];
[super dealloc];
}
Now, I must own at least 15 to 20 books on iOS development. I can't say that I have ever seen any code in these books proposing that one do anything other than:
[someproperty release];
Is there a compelling reason to edit a bunch of files of code that works perfectly well to adopt Apple's recommendation? How about future work? Or, are they pretty much equivalent?
Apple's document appears to apply only if you have synthesize-by-default turned on. If you have it turned off, which seems to be the default case, you need #synthesize, which gives you access to variables directly.
Personally, I do:
#synthesize someProperty=_someProperty;
just so I can then do:
- (void)dealloc {
[_someProperty release];
[super dealloc];
}
See Jeff LaMarche's blog for more.
On the modern runtime, you no longer have to declare instance variables for properties, nor do you have to write #synthesize in the implementation. If your code already has the instance variables declared, then there's no reason to replace code that calls release with a call to a set accessor (the first quote you pasted even states that).

Order of release and dealloc messages

What is the recommended way of doing this. Should I call super dealloc first or last or doesn't it matter?
- (void)dealloc
{
[super dealloc];
[orderNumber release];
[orderDate release];
}
Also when it comes to overriding methods like didViewLoad - should I call super first or last?
Always call [super dealloc] last or you might easily come into trouble because you're working on a stale object.
With didViewLoad you normally call it before your own code as you want the standard initialization stuff executed before. I've seen examples in Apple's code that don't call the super implementation at all, though, so maybe there's not much going on anyway.
In this case call the super after you have released all your properties/iVars. For viewDidLoad/willAppear/etc. I usually call the super first. The order matters when your custom class is relying on an object that is created by the super. For the default viewDidLoad this is not the case so it is preference(I believe).
There is no general rule - you chose to override the method, what does it do? Do you want it to happen before or after your custom implementation?
didViewLoad doesn't appear to be a real method.
We know that [super dealloc] destroys the current object completely, so any code that comes after it is wrong. So, in this case, call [super dealloc] last.
The pointers orderNumber and orderDate are held inside your object.
[super dealloc] deallocates your object (aka self).
Once you deallocate your object you must not rely on the things inside it (e.g. orderNumber) having the values they did before you deallocated it.
Therefore, deallocate the members before deallocating the self object.
The opposite holds true for init functions - you can't initialise the pointers until after your object is constructed, so [super init] comes before you initialise the members.
Regarding viewDidLoad (et al), you do whatever works. If you have stuff you want to happen before the superclass does its thing, then you do it before you call the superclass method, and likewise for stuff you want to happen afterwards.
If you don't know whether your code should run before or after, then it probably doesn't matter.

Using self on iVars in dealloc?

Usually I write my dealloc to look like this:
- (void)dealloc {
[coffeeList release];
[super dealloc];
}
But today I typed (see below) and was a little puzzled why I got an error running the code through the CLANG static analyser. As I say I don't usually add self to iVars in dealloc, but was just a little curious when I spotted this as to what was going on.
- (void)dealloc {
[[self coffeeList] release];
[super dealloc];
}
gary.
I'm just guessing that clang notices [self something] release (or [self.something release]) goes against the memory management conventions. An object returned from a method not having "new", "init", or "copy" in its name should be autoreleased, so releasing it again would appear to be an over-release error.
Because that's really bad form, and goes against how you should be doing things. CSA doesn't just check for semantic errors, it also checks that you're doing things the way you should be. Where the way you should be, is the way things are done in the documentation.
Is coffeeList declared as a property (and set to retain)? Then you should probably do:
[self.coffeeList release];