初学者关于内存的思考(不断加深不断更新中)

1、

从最简单的说起,先看例子,看注释:

-(void)fun1
{
str1 = @"我是str1";
NSLog(@"str1的conut: %d",[str1 retainCount]);//-1 之所以为-1,是因为直接赋值后,"我是str1"被放在常量区,没有所谓引用
}

-(void) fun2
{
str2 = [NSString stringWithFormat:@"我是str2"];
NSLog(@"str2的count: %d",[str2 retainCount]);//1。注意:stringWithFormat里面已经包含alloc和autorelease了
  //[str2 release];如果加了这句,程序就崩溃。因为已经包含了autorelese,下面fun4的str2就是非法引用
}

-(void) fun3
{
str3 = [[NSString alloc]init];
str3 = @"我是str3";
NSLog(@"str3的count: %d",[str3 retainCount]);//-1 alloc跟init被忽略了,效果如fun1
}

-(void) fun4
{
NSLog(@"str2:%@",str2);
NSLog(@"str1:%@",str1);
  NSLog(@"str3:%@",str3);
}

在外面:
    NSLog(@"str2 final count:%d",[str2 retainCount]);//1 仍旧是1,因为由编译器来负责管理(autorelease)
    NSLog(@"str3 final count:%d",[str3 retainCount]);//-1

由上面的代码示例可以看出直接赋值跟用*with*方法赋值的区别。

stringWithFormat里面已经包含alloc和autorelease。确切地说,*with*方法都包含了alloc以及autorelease

2、
在声明为@property (nonatomic, retain) UIAlertView *alert时,这里的retain不是摆设,而是retain了一次,这就刚好跟dealloc对应,在dealloc里面release
计数器加1了。所以在还没alloc之前,retainCount为1。
在.h中声明alert为成员变量,并设为property的retain属性   

UIAlertView *tmpAlert = [[UIAlertView alloc]initWithTitle:tempStr
message:nil
delegate:self
cancelButtonTitle:@"取消"
otherButtonTitles:@"确定",nil];
self.alert = tmpAlert;
[tmpAlert release];
[alert addSubview:view];
[alert show];
在上例子中,一般就这么用,不要直接轻易去对alert进行alloc,这样很容易出错。常见的做法如上,设一个临时变量tmpAlert,赋值给alert后就release掉。注意,是赋值
给self.alert,而不是alert。别忘了,self.alert = tmpAlert 这句话等价于[alert release];alert = [tmpAlert retain];(为什么?)所以,为了避免额外的
错误,尽量在.h中声明property/retain属性,要赋值的时候就用self.***。


3、成员变量跟property不一定要对应存在,没有成员变量只有property也是合法的,self.***访问的就是property。

4、对一个尚未分配内存的变量进行release是合法的。但是一旦你alloc+init了之后,就不能那么随便release。请看下面比较:
    UIAlertView *alert = nil;
    [alert release];//正确
    
    UIAlertView *alert2 = [[UIAlertView alloc] init];
    [alert release];
    [alert release];//报错
    
    NSString *str = nil;
    [str release];//正确
    
    NSString *str2 = [[NSString alloc] init];
    [str2 release];
    [str2 release];//正确!!!!!

可以看出,NSString类型是个特列,不管你有没有alloc分配内存给他,都可以随时release。

从这个例子我们也可以看出,对于工程里面的成员变量,不应该随意去设@property属性,因为这样会暴露给别的类。但是这时候会有这样的烦恼,没有了(retain),似乎后面的内存管理会变得麻烦些。所以产生了另外一种方式,在.m文件里面,凡是用该成员变量(假设为A)的地方,首先要在init里面把A置为nil,这是为了后面release的方便,不会出错(对nil对象release是不出错的)。然后凡是对该变量进行赋值的地方,都要先release,赋值完后再retain,养成习惯吧,兄弟。

 

5、@property、@synthesize

这两个关键字是让成员变量生成相应的setter、getter。setter里面已经包含了必要的retain、release。平时我们用self.****就是访问setter,而没加self的就是访问普通的成员变量。

看个例子:

 @interface Photo : NSObject

{

NSString* caption;

NSString* photographer;

}

- (NSString*) caption;//getter 

- (NSString*) photographer;

- (void) setCaption: (NSString*)input;//setter,注意其默认的名字set+***

- (void) setPhotographer: (NSString*)input;

@end

用@property实现简化如下:

@interface Photo : NSObject

{

NSString* caption;

NSString* photographer;

}

@property (retain) NSString* caption;

@property (retain) NSString* photographer;

@end

这里的retain意思是,setter应该对input进行retain。
http://cocoadevcentral.com/d/learn_objectivec/                    原链接

 

- (void) dealloc

{

self.caption = nil;

self.photographer = nil;

[super dealloc];

}

6.下面介绍几个个人比较容易混淆的东西,非常实用!先总说一下,原则是:

原则1:往数组里填东西或者删除东西,数组本身的引用计数不改变!!!!,变的是被拿去添加的元素,引用计数相应增减

原则2:往view添加subview或者removeview,superView本身引用计数都不改变!!!变的是被拿去添加的subview,引用计数相应增减

原则3:subview可分为两种,一种是不需要控制的静态view,一种是被设为成员变量长期控制的动态view。 假设subview添加到superview中,并且以后不打算做改变,则应这么写:

uiview *subview = new subview;//subview:1

//若是动态view,则是_subView = new subview;//subview:1

[superView addSubView:subview];//subview:2, superview:1

[subview release];//subview:1

静态view:在dealloc中就不用再释放了!因为大原则是“谁申请谁释放”,你只申请了一次,自然只需要释放一次。剩下的1个引用什么时候减掉呢?当superView释放的时候自己释放掉!

动态view:若是动态view,则完全可以跟静态view一样,这样的话Dealloc里面就是空空的,这也是可以的;另一种是在上述步骤中不做release操作,统统保留到dealloc中做

 






posted @ 2012-03-15 14:58  编程小翁  阅读(1202)  评论(1编辑  收藏  举报
我是来自厦门的Jilon. 翁,请关注我的微博:真实的weng,或关注微信:Jilon