iOS 内存
转:http://www.devdiv.com/forum.php?mod=viewthread&tid=90078
一、//未申明属性的一般空间的分配
@interface TextDemoViewController : UIViewController {
NSMutableArray *myArray;
}
@end
- (void)viewDidLoad {
[super viewDidLoad];
myArray=[[NSMutableArray alloc]init];//一般赋值
NSLog(@"%d",[myArray retainCount]);// retaincount为1
}
- (void)dealloc {
[super dealloc];
[myArray release];
}
二、//申明为属性
@interface TextDemoViewController : UIViewController {
NSMutableArray *myArray;
}
@property(nonatomic,assign)NSMutableArray *myArray;
@end
@synthesize myArray;
- (void)viewDidLoad {
[super viewDidLoad];
myArray=[[NSMutableArray alloc]init]; //一般赋值
// self.myArray=[[NSMutableArray alloc]init];//属性赋值
NSLog(@"%d",[myArray retainCount]);
/********************************
这里一般赋值与属性赋值是看似是等同的,这是因为变量名和属性名相同
**********************************/
}
- (void)dealloc {
[super dealloc];
[myArray release];
}
三、//做下小小的改动后
@interface TextDemoViewController : UIViewController {
NSMutableArray *_myArray;
}
@property(nonatomic,assign)NSMutableArray *myArray;
@end
@synthesize myArray=_myArray;
- (void)viewDidLoad {
[super viewDidLoad];
_myArray=[[NSMutableArray alloc]init]; //一般赋值
// self.myArray=[[NSMutableArray alloc]init];//属性赋值
NSLog(@"%d",[_myArray retainCount]);
/********************************
经过改动后上面的赋值是等同的,我想这样的机制应该很明了了,
synthesize的功能就是set函数的功能,myArray是形参,_myArray是实参
所以在运用myArray不加self的话是会出错的,因为他是一个属性,不是确切的对象
所以对于什么时候加self 什么时候不加self就一目了然了,如果你想看得更清楚的话就建议将属性 名 和实际的实参名取不同的名字
**********************************/
}
- (void)dealloc {
[super dealloc];
[_myArray release];//所以在内存释放的时候我们只能释放实参的空间,而形参是没有地址空间的
}
四、//我们将@property(nonatomic,assign)NSMutableArray *myArray;
替换成:@property(nonatomic,retain)NSMutableArray *myArray;
- (void)viewDidLoad {
[super viewDidLoad];
_myArray=[[NSMutableArray alloc]init]; //一般赋值
//self.myArray=[[NSMutableArray alloc]init];//属性赋值
NSLog(@"%d",[self.myArrayy retainCount]); //此时的retaincount为2 这就有了内存泄露
//将上面的方法改成如下:
NSMutableArray *tempArray=[[NSMutableArray alloc]init];
self.myArray=tempArray;
[tempArray release];
NSLog(@"%d",[self.myArray retainCount]);//此时的retaincount为1 没有内存泄露
}
设为属性的对象或者基本数据类型是为了在其他类的对象中调用该对象的属性
在上面的例子中加入方法:
-(void)setMyArray:(NSMutableArray *)arr{
self.myArray=arr;
}
那么在其他对象的调用中
TextDemoViewController *viewController=[[TextDemoViewController alloc]init];
NSMutableArray *array=[[NSMutableArray alloc]init];
viewController.myArray=array; //通过属性传递
[viewController setMyArray:array]; //通过方法传递
这两种都可以实现对myArray的赋值,效果相同。
但是属性的话范围更广,比如我的属性是一个UILabel的控件的话,我的方法是改变label的显示,而属性的话就可以改变它的框架,凡是label所具有的属性都可以设置,这就涉及到一个关于私有成员的概念,申明为属性的话相当于申明成了公有成员,外部的对象可以改变它具有的所有属性。
再回到上面的两个方法中,如果我们在viewDidLoad中已经为该数组分配了空间,那么我们每一次的myArray=array其实是改变了它起初的分配空间,这里实际上有内存的泄露:
看一个简单的例子: NSMutableArray *tempArray1=[[NSMutableArray alloc]init];
self.myArray=tempArray1;
[tempArray1 release];
NSMutableArray *tempArray2=[[NSMutableArray alloc]init];
self.myArray=tempArray2;//这里self.myArray丢弃了原先的空间,被tempArray2空间所取代,那么 原先的空间并没有释放,所以这里需要改动为 [self.myArray addObjectsFromArray:tempArray2];这 样的话self.myArray的空间还是原来tempArray1申请的空间,变化的只是它的空间里存放的数据
[tempArray2 release];
五、//delegate-----特殊的属性
在我认为委托或者说代理其实只是类的一种特殊属性,只是这样的属性是任意的Id类型的对象,代理是让外部对象调用内部方法的一种实现方法,比如常见的TableView的datasourse,因为内部无法对自己的数据进行加载,所以我们需要在外部对其进行数据操作。
一般情况下是这样的,例如ViewControllerOne里申明了一个delegate和一个代理的方法,ViewControllerTwo中实例化了一个ViewControllerOne的对象,那么我申明ViewControllerOne的代理对象是ViewControllerTwo,也就是ViewControllerTwo是ViewControllerOne的一个属性,这之间其实是一种相互包含的关系。