Im very confused with the memory management.
Declared variable allNoticeArray in .h file:
#interface NoticeViewController : UITableViewController
{
NSMutableArray *allNoticeArray;
}
#property (nonatomic, retain) NSMutableArray *allNoticeArray;
#end
Alloc and init the variable in .m file:
#implementation NoticeViewController
#synthesize allNoticeArray;
- (void)viewDidLoad
{
[super viewDidLoad];
self.allNoticeArray = [[[NSMutableArray alloc] init] autorelease];
}
- (void)dealloc
{
[super dealloc];
/*
***should I release allNoticeArray here or not?***
*/
//[allNoticeArray release];
}
Should I release the allNoticeArray in dealloc function or not?
Thank you in advance!
It looks like you're manually managing your memory rather than using ARC.
If you're using IOS5 it might be easier for you to convert your project to ARC, then you won't have to worry about dealloc in this context.
If you don't want to use ARC you do need to release it in this context because you alloc'd it in viewDidLoad. You might also be interested in this article about dealloc.
Yes, you have to release the object. You could do the below in your dealloc method which will release your object.
self.allNoticeArray = nil;
REASON:
Although you have autoreleased the array you have declared your property as retain. So the object will be retained and used. So to totally remove the object from memory you should again call release over it.
You can learn everything about memory management here https://developer.apple.com/library/mac/#documentation/Cocoa/Conceptual/MemoryMgmt/Articles/MemoryMgmt.html
When not using ARC you should use the release in the dealloc. You are right in saying that your retain in the .h file increases the retain count by one. The Alloc/Init creates an object with a retain count of one. The auto release would counter that retain, however your dealloc release would count the retain in the .h.
Setting self.allNoticeArray=nil; is not the same as a release, but the link from sElan is a great link.
The rule of pre-ARC memory management is this: if you alloc, retain, or copy an object you must release it later or it will leak. Your property is set to retain, so whatever value it holds will be retained. You must balance it with a release in dealloc.
The short answer is NO, but you are doing a few things that are not recommended. In your code you are retaining your array twice in the single line. In the code below it is only retain once.
You should initialize the array like so -
NSMutableArray *array = [[NSMutableArray alloc] init] autorelease];
self.allNoticeArray = array;
I would recommend you look into using ARC, it makes memory management a non issue in IOS 5.
Related
#interface Rectangle
#property (retain) UIView *view;
#end
#implementation Rectangle
CGRect frame = CGMakeRect();
self.view = [[UIView alloc] initWithFrame:frame]
Student *student=[[Student alloc]init];
[student release]; // not using this but using dealloc on it see below
(void) dealloc {
[_view release];
[super dealloc];
[student dealloc];
}#end
My question is:
here why we have to deallocate the memory on super object ???? what happen if we deallocate the memory on student with release it?????
retain and dealloc are not compliments. retain and release are complements, adding to and subtracting from an object's reference count respectively.
If your synthesized setter does a retain, then your dealloc should do a release (and a [super dealloc]).
The modern approach is to use ARC, drop the #synthesize, and always refer to your properties with the synthesized setters and getters, like this:
id foo = self.property;
self.property = foo;
Except in init, where it's better to say:
_property = foo;
Without ARC I write the set methods like this
- (void)setArr:(NSMutableArray *)arr
{
_arr = [arr retain];
}
but Xcode tell me "'retain' is unavailable: not available in automatic reference counting mode" when enable ARC.
_arr = arr; is all that is necessary. But practically, based on your code sample, there is no need to write the setter yourself. Simply declaring #property NSMutableArray *arr; in your header file is enough for the compiler to generate the setter and getter. When compiling with ARC enabled, retain and release calls are generated by the compiler for you.
When using arc, all you have to do is let the system handle the retain/release, this means:
- (void)setArr:(NSMutableArray *)arr
{
_arr = arr;
}
However, if your setter is as simple as this its just easier to let the compiler synthesize it.
Previously you had to use #synthesize, but now declaring it as a property on the header is enough.
#property (strong, nonatomic) NSMutableArray *arr;
In my iOS project i am creating an NSArray that can contains integer values. There are several functions in this class that do their task on that NSArray. So i thought to create NSArray as private attribute of that class. In viewDidLoad i am allocating memory to this array i.e
myArray = [[NSArray alloc] init];
myArray will be used in several method of this class. When i analyze my code it shows memory leak as i am allocating myArray and not releasing it.
If i write [myArray release] in dealloc or viewDidUnload warning still there. If i release myArray in last method of class that is using this array, xCode wont allow me to do.
Here is How i am declaring it in my class
.h file
#interface FightVC : UIViewController
{
NSArray *myArray;
}
I want to know what is possible solution of this. other then using autorelease . I don't want to make it public so i am not writing this array as property.
Thanks in advance
Using a private #property as mentioned in the other answer is probably the nicest and cleanest way to do this. Raw instance variables aren’t a very modern way of doing things. However, if you are going down that road, you can implement a getter for your ivar in which you release the old ivar and retain the new one:
- (void)setMyArray:(NSArray *)array {
[myArray release];
myArray = [array retain];
}
That’s the typical pattern anyway (which is what having an #property does for you automatically).
After that, you can create the array, use the setter, and then release the object:
NSArray *newArray = [[NSArray alloc] init];
[self setMyArray:newArray];
[newArray release];
That should keep the analyzer from squawking at you. A few things stick out to me though:
1) [[NSArray alloc] init] isn’t likely to do what you want it to do. It’s going to create an empty, immutable array. You probably either want an NSMutableArray, or you want to instantiate it with objects already in it using a different initializer.
2) NSArrays aren’t really suited for holding integers themselves, they hold objects. You can either use an NSPointerArray or you can put the integers into NSNumbers and put them into an NSArray.
To make a property private, you have to create an anonymous category.
In your .m file:
#interface myClass ()
#property (nonatomic, retain) NSArray *myPrivateArray;
#end
#implementation myClass
// Class code here
#end
To release your array, simply set the property to nil.
self.myPrivateArray = nil;
I need to get things clear about Objective-C memory management:
If I declare an object in the class header as ivar without #property:
#interface MyFacebooDelegate : UIViewController
{
TableViewController *tableController;
}
...
#end
and some where in the code for example in - (void)viewDidLoad I do :
tableController = [[TableViewController alloc] init];
so where is best way to release it. What if I make the instant object a property what will be the different? and how the memory management will be too
#interface MyFacebooDelegate : UIViewController
{
TableViewController *tableController;
}
...
#end
#property (nonatomic, strong) TableViewController *tableController;
What the following syntax do exactly for the object viewController:
.h
#interface AppDelegate : UIResponder <UIApplicationDelegate>
#property (strong, nonatomic) ViewController *viewController;
#end
.m
#implementation AppDelegate
#synthesize window = _window;
#synthesize viewController = _viewController;
- (void)dealloc
{
[_window release];
[_viewController release];
[super dealloc];
}
.....
#end
If I want to return an object through a method to another class, do I need to autorelease it in the method body first and then retain it in receiver side?
for example this method what exactly to do in the method body and in the receiver side too:
-(NSString *)getFriendId
{
NSArray *ar = [NSArray arrayWithObjects:#"1",#"2",#"3", nil];
return [ar objectAtIndex:0];
}
I know this a lot but I am really confused and need your help.
1) best way is in dealloc; or right before re-setting it.
2) a property does the retain/release for you. But WARNING! You keep mixing up things. You use "strong" here, which relates to ARC. If you really insist on using classic retain/release (you shouldn't) then use (nonatomic, retain) instead.
3) Your properties get deallocated on dealloc. Again, strong is wrong here.
4) Yes. Ideally you should. Another reason why ARC is awesome, it does this all for you, automatically.
tl;dr: Use ARC. Never go back. (But still learn manual memory management)
ARC is the answer for your all memory management question. Very import note on Strong and Weak property in addition to ,
iOS Strong property: So strong is the same as retain in a property declaration before ARC. For ARC projects I would use strong instead of retain, I would use assign for C primitive properties.
iOS outlets should be defined as declared properties. Outlets should generally be weak, except for those from File’s Owner to top-level objects in a nib file (or, in iOS, a storyboard scene) which should be strong. Outlets that you create will therefore typically be weak by default, because: Outlets that you create to, for example, subviews of a view controller’s view or a window controller’s window, are arbitrary references between objects that do not imply ownership.
I'm using leaks tool of instruments. It says that I have some leaks in the init method. It shows that NSMutableArray has leak.
I don't see any leaks.
#interface BookSettings : NSObject
#property (nonatomic, retain) NSString *title;
#property (nonatomic, retain) NSMutableArray *authors;
#end
- (id)init
{
self = [super init];
if(self)
{
title = [[NSString stringWithString:#""] retain];
authors = [[NSMutableArray alloc] init];
}
return self;
}
- (void)dealloc
{
[title release];
[authors release];
[super dealloc];
}
The provided code is OK, the problem is somewhere else where authors is retained without a balancing release. Leaks just points to the place ivar is created, not where the missing release should be. Check all the places where the retain count is increased.
If you need to see where retains, releases and autoreleases occur for an object use instruments:
Run in instruments, in Allocations set "Record reference counts" on on (you have to stop recording to set the option). Cause the problem code to run, stop recording, search for there ivar of interest, drill down and you will be able to see where all retains, releases and autoreleases occurred.
Seriously consider using ARC, there is little reason not to, ARC supports back to iOS 4.x.
BTW:
title = [[NSString stringWithString:#""] retain];
can be more compactly written:
title= #"";
I think it's from title.
You already have that property nonatomic, retain, so it this means a retain count of 1.
Then you specify another retain, making the retain count 2.
In the dealloc, you release it once, decreasing the retain count to 1. So this 1 reference that keeps retaining the string is the leak.
I don't understand why you are initialising the string like that anyway...