内存管理

内存管理的一些总结:
1、全局类型的变量初始化的时候 变量名=[[alloc]init],最后在delloc里面释放,如果一些变量必须要用静态方法创建,那么可以变量名=[[类 静态方法]retain],在delloc释放
2、局部类型的变量初始化的时候如果是alloc创建的,那么在使用完成后release,如果是类调用静态方法创建的,不管他
3、使用委托时,如果出现了循环引用,不能用retian必须用assign

可变数组一般用retain
原因:
如果一个可变数组用copy如:@property (nonatomic,copy)NSMutableArray *arr;
通过copy出来的内存是不可变的,那么,当arr用addObject的时候就报错了
.h文件

//
//  ZQAppDelegate.h
//  Arc
//
//  Created by mac on 15-5-13.
//  Copyright (c) 2015年 KangZhiQiang. All rights reserved.
//

#import <UIKit/UIKit.h>

@interface ZQAppDelegate : UIResponder <UIApplicationDelegate>

@property (strong, nonatomic) UIWindow *window;
@property (nonatomic,retain) UIView *myView;
@property (nonatomic,assign) UIView *myView0;
@property (nonatomic,copy)NSMutableArray *arr;
@property (nonatomic,retain) UIButton *myBtn;
@end

.m文件

//
//  ZQAppDelegate.m
//  Arc
//
//  Created by mac on 15-5-13.
//  Copyright (c) 2015年 KangZhiQiang. All rights reserved.
//

#import "ZQAppDelegate.h"
#import "ZQViewController.h"
@implementation ZQAppDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    self.window = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];
    // Override point for customization after application launch.
    self.window.backgroundColor = [UIColor whiteColor];
    [self.window makeKeyAndVisible];
    ZQViewController *zq=[[ZQViewController alloc]init];
    self.window.rootViewController=zq;



    //只要我们自己alloc new retain copy这些内存的时候,他的引用计数会增加,并且只要我们自己让他的引用计数减少时候,他才会减少,系统不会让其减少
    UIView *vi=[[UIView alloc]init];
    //输出引用计数
    NSLog(@"%d",[vi retainCount]);
    //release是异步过程,比较安全的写法是在内存释放完成后把指针置为nil
    [vi release];

    vi=nil;
    [vi release];
    [vi release];
    [vi release];
    [vi release];
    vi=nil;//空指针可以做任何事情,并且可以无限release

    vi.backgroundColor=[UIColor redColor];
    vi.tag=5;
    vi.frame=CGRectMake(0, 0, 30, 30);
    NSLog(@"%d",[vi retainCount]);
    NSLog(@"%d",[vi retainCount]);
    NSLog(@"%d",[vi retainCount]);
    NSLog(@"%d",[vi retainCount]);

    //内存管理:谁创建谁释放
    UIView *vi2=[[UIView alloc]init];
    NSLog(@"%d",[vi2 retainCount]);//此时输出1
    //当一个视图放在另一个视图上得时候,系统会让其引用计数增加
    [self.window addSubview:vi2];//此时系统让其应用计数增加,所以我们不用管
    NSLog(@"%d",[vi2 retainCount]);//此时输出2
    [vi2 release];
    //当一个视图从父视图中移除的时候,系统会让其引用计数减少
    [vi2 removeFromSuperview];
    //放入数组 放入导航器 UIAlertView show的时候,系统都会让其引用计数增加,当从数组中移除  从导航器重移除  UIAlertView 点击按钮消失时候系统也会让其引用计数减少

    //当一个类的内存通过一个类的静态方法创建的时候,他的引用计数也为1,只不过这块内存是自动释放的
    UIButton *btn=[UIButton buttonWithType:UIButtonTypeSystem];
    NSLog(@"btn%d",[btn retainCount]);
    [btn addTarget:self action:@selector(onClick:) forControlEvents:UIControlEventTouchUpInside];
    btn.frame=CGRectMake(0, 0, 100, 40);
    btn.backgroundColor=[UIColor redColor];
    [self.window addSubview:btn];
    NSLog(@"btn%d",[btn retainCount]);


    //总结:
    //(1)局部变量是对象类型,如果创建的时候是alloc new copy retain 必须要在使用完成后release
    //(2)局部变量是对象类型,如果是类调用静态方法创建的时候,不能写release
    UIView *vi3=[[[UIView alloc]init]retain];//增加2
    NSLog(@"888>>>>%d",[vi3 retainCount]);

    UIView *vi4=[[[[UIView alloc]init]retain]autorelease];//增加2,又自动减1
    NSLog(@"vi4>>>>%d",[vi4 retainCount]);


    //全局类型的变量因为我们要在多个方法中进行访问,所以这个对象不能够是自动释放的,需要手动创建
    _myView=[[UIView alloc]init];
    //此处button的创建是个特例,因为我们只能用静态方法创建,那么此时其内存是自动释放,那么我们要在其他方法里边用的时候可能已经被释放了,所以我们应该强制的给其加个retain,让其引用计数加1,这样就不会出现程序崩溃的问题了,但是既然我们让引用计数加1,我们就需要再dealloc方法中release
    _myBtn=[[UIButton buttonWithType:UIButtonTypeSystem]retain];
    [self.window addSubview:_myBtn];



    UIView *vi5=[[UIView alloc]init];//alloc,vi5的引用计数+1

    self.myView=vi5;//myView是retain,所以两个对象的引用计数都+1,变成2
    NSLog(@"%p>>>>>%p>>>>%d",self.myView,vi5,[vi5 retainCount]);
    //两个内存地址想的,引用计数都为2

    UIView *vv=[[UIView alloc]init];
    self.myView=vv;//此处调用下边的setMyView方法,让自身减1.然后又用retain+1
    NSLog(@"110====%p>>>>>%p>>%d>>>%d",self.myView,vv,[vi5 retainCount],[vv retainCount]);
    两个内存地址想的,10====0x8d8fa50>>>>>0x8d8fa50>>1>>>2

    UIView *vvv=[[UIView alloc]init];
    self.myView=vvv;
    NSLog(@"%p>>>>%p>>>>>%d>>>>%d",self.myView,vvv,[vv retainCount],[vvv retainCount]);

    UIView *vv0=[[UIView alloc]init];
    self.myView0=vv0;//myView0是assign,所以两个对象的引用计数都不变,都为1
    NSLog(@"110====%p>>>>>%p>>%d>>>%d",self.myView0,vv0,[self.myView0 retainCount],[vv0 retainCount]);
    //110====0x8d98040>>>>>0x8d98040>>1>>>1

    UIView *vvv0=[[UIView alloc]init];
    self.myView0=vvv0;//myView0是assign,所以两个对象的引用计数都不变,都为1
    NSLog(@"%p>>>>%p>>>>>%d>>>>%d",self.myView0,vvv0,[vv0 retainCount],[vvv0 retainCount]);
    //0x8d90f00>>>>0x8d90f00>>>>>1>>>>1


    //个人理解,对不可变数组系统自动用浅copy,然后让两个指针指向同一块内存空间,原因是不可变数组不会改变,所以让两个指针指向同一个也不会出现问题,而对于可变数组,系统会自动再分配一块内存空间,两块空间中的内容相同,这样当一个内存中的内容改变的时候,也不影响另一块的内容
    NSArray *array=[[NSArray alloc]initWithObjects:@"0", nil];
    self.arr=array;//arr为copy,array是不可变数组,所以为浅copy,两个指针指向同一块内存空间,引用计数+1.变成2
    NSLog(@"%p>>>>%p>>>>%d",self.arr,array,[array retainCount]);
    //0x8d98d30>>>>0x8d98d30>>>>2

    NSMutableArray *muArr=[[NSMutableArray alloc]initWithObjects:@"0", nil];
    self.arr=muArr;//arr为copy,muArr是可变数组,所以为深copy,两个指针指向不同内存空间,引用计数都为1
    NSLog(@"%p>>>>%p>>>%d>%d",self.arr,muArr,[self.arr retainCount],[muArr retainCount]);
    //0x8d94270>>>>0x8d6db70>>>1>1
    return YES;
}
//assign
- (void)setMyView0:(UIView *)myView0{
    if (_myView0!=myView0) {
        _myView0=myView0;
    }
}
//retain 的set方法
- (void)setMyView:(UIView *)myView{
    if (_myView!=myView) {
        [_myView release];
        _myView=[myView retain];
    }
}
//copy
- (void)setArr:(NSMutableArray *)arr{
    if (_arr!=arr) {
        [_arr release];
        _arr=[arr copy];
    }
}
//当一个类的对象over的时候,就会调用其dealloc方法,在这个方法里边要去释放属性
- (void)dealloc{
    //此处要先释放全局的属性,然后再调用super的dealloc方法,比如一颗大树创建完成后,我们在其上边加了枝叶,我们应该先把其枝叶去掉之后再把大树的树干去掉
    [_myView release];
    [_myBtn release];
    [super dealloc];
}
- (void)onClick:(UIButton *)btn{


}

@end
  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论

“相关推荐”对你有帮助么?

  • 非常没帮助
  • 没帮助
  • 一般
  • 有帮助
  • 非常有帮助
提交
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值