confused by ARC - iphone

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.

Related

Objective C ARC equivalent for self?

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

Objective-C - allocation/initialization of an object with ARC

I was wondering if I can directly alloc, init an ivar now with ARC (Because if I remember well it wasn't possible without ARC because it would leak memory no) ?
Example (consider an ivar declared like this) :
#property (nonatomic, strong) NSArray *myArray;
#synthetize myArray = _myArray;
And then do
self.myArray = [[NSArray alloc] initWithObjects:object1, object2, nil]; //I know I could directly use [NSArray arrayWithObjects:...] but that's the purpose of my question
Yes.
The only difference between using alloc/initWithObjects: and arrayWithObjects: is that the former leaves you with a retained object, while the second doesn't. If for some reason you wanted to use the former to initialize a property, you'd want to add a call to autorelease to avoid a leak. So you'd do this:
self.myArray = [[[NSArray alloc] initWithObjects:foo, bar, nil] autorelease];
You're correct that with ARC, the compiler will take care of adding that for you, so you can now just say:
self.myArray = [[NSArray alloc] initWithObjects:foo, bar, nil];
It would, if you didn't release it on your dealloc method. With ARC you are responsible for the allocation. In the dealloc method, using ARC, you can still release resources using self.ivar=nil (but ARC is already doing that automatically for you), but not using the word release explicit. Also, ARC does not allow you to call [super dealloc].
You can still alloc and retain. The object lifecycle remains the same, i.e. objects get release when reatin count drops to 0. All that ARC does for you is place the objects in an autorelease pool and correctly release it, where you should have done. You can still override dealloc.
You can find good article about ARC here

Correct way of releasing variables using Dealloc and ViewDidUnload

I've been trough some tutorials and some information, but I dont have a straight answer about the best way or the best place to release variables.
Lets see this situation, I have these 2 variables:
#property (nonatomic, strong) IBOutlet UIButton *myButton;
#property (nonatomic, strong) NSString *myString;
...
#synthesize myButton = _myButton, myString = _myString;
Is this the best way of releasing them?:
-(void)viewDidUnload {
self.myButton = nil;
self.myString = nil;
[super viewDidUnload];
}
-(void)dealloc{
[_myButton release];
[_myString release];
[super dealloc];
}
I understand more than enough when dealloc is called, and when viewDidUnload is called, I just want to know if that way is correct, and why it has to be done in that way.
Thanks guys
It is recommended to not use property accessor methods in init and dealloc, since they might expect some other information in the object to exist. If you know what you are doing, there is really no problem of using self.myButton = nil also in dealloc. However, there is really no use of setting them to nil since the object is being destroyed - unless some code is accidently run from dealloc (as the accessor methods I mentioned above).
In viewDidUnload, you want to set your members to nil instead of only releasing them, since your object will continue to exist and does not want to access dangling pointers.
So, your example should be the best performance and safest way of programming.
There are other ways, such as not declaring the IBOutlets as properties, or declaring them as properties without retaining. I find that in most cases I prefer to have them be retained properties, which I then have to explicitly release. An example of this is when you switch from one view controller to another. As one view controller is dismissed, its views are removed and they are released. Any IBOutlet UILabels on that view would get released too if I don't have them retained. That means that when I flip back to the old view, I have to go through and reset my labels and controls to their last values, when I could have easily kept them saved if I just retain the IBOutlet.
I have read the documentation about the use of the viewDidUnload method. I thought I did understand the meaning of this method
1) I use retain with #propery in the .h file and #syntesize in the .m-file. I assign object with a value using self.object = something. In this case I would set self.object = nil; in the viewDidUnload method.
2) I do not retain the object in the .h-file but I am allocing and init the object in the viewDidLoad method. In the dealloc method I have the [object release]; In the viewDidUnload method I also set [object release]; because the next time the view will appear, the object will be created in the viewDidLoad method
Hope, this will help you...

Require some understanding for Singleton Pattern

I am going to paste a code here and had a question regarding that which I wanted to understand merely, based on the logical way.
#interface MySingleton : NSObject {
NSString *enteredCode;
}
#property (nonatomic, retain) NSString *enteredCode;
#end
#synthesize enteredCode;
-(void) addInput:(NSString *) input
{
self.enteredCode = [self.enteredCode stringByAppendingString:input];
}
- (void)dealloc {
[enteredCode release];
}
#end
In my code, if I utilize "self.enteredCode = [self.enteredCode stringByAppendingString:input];"
everything works fine but "enteredCode = [self.enteredCode stringByAppendingString:input];" it gets exc_bad_access, and I am just wondering why this case be?
I am just trying to understand what difference really does it makes without having self there?
Thanks.
This is not to do with singletons. When you do self.enteredCode you are going through the property which is set to 'retain'. The stringByAppendingString method is a convenience method with returns an autoreleased object to you, meaning that it will be released at some point on the next run loop. You need to retain this value to stop it being released, which is fine when you assign it through the property as it is properly retained by you and you can use it as you like.
When you reference the variable directory (without the self.) you bypass this and as such you don't ever retain the value, the value is subsequently released and you reference bad memory and BOOOOOOOOM, bad access.
when you call self.enteredCode = XXX it will call [self setEnteredCode:XXX]. Since you are using a retain property this will release the old value of enteredCode, and retain the new value.
if you directly manipulate the enteredCode variable you will have memleaks and crashes because it will try to release something that is not retained later.
If I understand correctly, self.enteredCode works but enteredCode fails.
If that's the case then I believe it's because you're bypassing the property and setting the iVar directly. That means you're assigned an auto released object and bypassing the retain mechanism.
Consider using something like _enteredCode for your iVars do it's clearer in your code when you're bypassing properties.

Getting a segfault (EXC_BAD_ACCESS) when deallocating variables

Ok I understand that this error mostly comes from sending a method call or trying to access a variable that has already been deallocated.
Here is the problem:
.h
#interface TimeEntry : NSObject <NSCopying, NSCoding> {
NSDate *from;
NSDate *to;
NSString *information;
}
#property (nonatomic, retain) NSDate *from;
#property (nonatomic, retain) NSDate *to;
#property (nonatomic, copy) NSString *information;
#end
And my classes' dealloc.
-(void)dealloc{
[super dealloc];
[to release];
[from release];
[information release];
}
This is the traceback thing when I get the EXC_BAD_ACCESS error
So I'm sending a message to an object that has been deallocated right?
So I turned on NSZombie and this STOPPED my crashes. It didn't give me some lovely crash report like I'd hoped. Instead it just kept the program from crashing.
In the dealloc method above if I comment out [to release] and [from release] the app doesnt crash. If I comment out just one of them.. it doesn't crash. In the debug window to and from have different memory addresses.
How can memory management be so hard!!!!
Any clues anyone?
Thanks,
Dan
Send the [super dealloc] message after you've released your variables, not before. [super dealloc] should be the last thing you do in your dealloc method.
Notice that you can send [nil release] and the application will not crash.
so checking for nil before releasing is some what unnecessary.
but i do agree that you should do [super dealloc] in the end of the dealloc procedure.
You should inspect all of the statements involving your properties to undestand where your variables are actually deallocated. Anyway, here is a quick solution that will avoid crashes, since your variables will be released if and only if they are still allocated objects:
-(void)dealloc{
if(to != nil{
NSLog(#"releasing: %#", to);
[to release];
}
if(from != nil{
NSLog(#"releasing: %#", from);
[from release];
}
if(information != nil){
NSLog(#"releasing: %#", information);
[information release];
}
[super dealloc];
}
Also, you may want to download, install and use the CLANG checker tool to understand why your code is wrong. This tool (which is already built for Leopard 10.5.x) may sometimes fail to provide the correct answer, but in my personal experience it never failed. I highly recommend it as one of your daily development tools.
You can download it from
http://clang.llvm.org/StaticAnalysis.html
Usage it really simple. Take a look at
http://clang.llvm.org/StaticAnalysisUsage.html#BasicUsage
In practice, you simply build your Xcode project using the command
scan-build -k -V xcodebuild
then, you inspect the resulting output HTML files using the command that will appears as output in your terminal window. These files will give you a detailed explanation of why something is wrong in your code.
Kind regards
Terry is correct, the [super dealloc] call must always be the last thing in -dealloc.
To be more specific, calling -[NSObject dealloc] is what deallocates the memory for the object. (In your case, you directly extend NSObject, but deeper inheritance trees create a chain of dealloc calls.) In a general sense, calling a parent's -dealloc method first will release resources inherited from the parent. If the child depends on any of those resources when it releases its own, you're up a creek. Since the parent cannot depend on the child, deallocing child resources first is the correct, safe way to do things.
The properties of the current object are stored in the object.
When you call [super dealloc], you are telling the system to destroy the object. After that call, you cannot rely on the properties being there or correct any more.
As previously stated, call it after you release the other members.