内存管理: alloc, retain, release, autorelease, copy, assign

内存管理必须遵守的原则 :  

(1) 使用者必须保证在他使用的周期内是安全的, 保证在不使用的时候消失 

(2) 谁让引用计数+1, 谁要负责引用计数-1 


1.  堆区内存有系统去管理(出生命周期被自动释放掉) 

     int a = 10; a在栈区  (所有的变量都在栈区, 除了静态static,和全局变量)


2.  People *p = [[People alloc]init]; 

     p 在栈区 指向 People产生的对象(堆区)


3.  堆区的每一块内存不能起名字, 栈区的变量指向堆区 

     (堆区 p  -> 栈区 对象)


4.   (1) p 释放掉 , 对象没有释放 -> 内存泄露

      (2) 对象释放掉, p没有释放掉 -> 野指针异常


5.  局部变量 和 成员变量的最大区别在于 变量名的生命周期

      (1)局部变量只是在方法内部定义的变量!

      (2)成员变量 作用于整个类的使用


6.  alloc 代表: 创建一个引用计数为1 的对象
     retain 代表: 引用计数 + 1
     release 代表: 引用计数 -1 
     autorelease 代表 : 将对象加入到自动释放池中, 相当于引用计数-1  (对象会被加入到离的最近的自动释放池中)
     当引用计数为0的时候调用dealloc的方法


7.  通过类方法(+方法)创建的对象是自动释放的, 返回的对象已经添加到自动释放 池中,   return[…  autorelease]


8.  在OC开发中, 空对象调用任何方法都是没有意义的

    空对象: 指针指向的地址是nil


9.  (1)如果在类中声明了成员变量, 那么成员变量的创建必须在init中且必须保证引用计数为1, 并在dealloc中释放

     (2)如果在类中声明了属性, 那么对属性赋值的时候必须通过点语法来进 行赋值(为了保证引用计数为1且避免内存泄 露),且必须在dealloc中释放


// 建立Car类 ,  并引入Student类作为属性

Car.h
#import <Foundation/Foundation.h>
@class Student;

@interface Car : NSObject

{
    //成员变量
    @public
    NSMutableArray *_array;
    
}

@property(nonatomic, retain)NSMutableArray *arr;

//把其他类写成属性
@property(nonatomic, retain)Student *stu;

//setter 方法
-(void)setArray:(NSMutableArray *)arr;

//getter 方法
-(NSMutableArray *)array;


//便利构造器
+(Car *)car;

@end


Car.m
#import "Car.h"
#import "Student.h"

@implementation Car


- (void)dealloc
{
    //不管是成员变量还是属性, 都需要在dealloc 写释放
   
    [_array release];
    [_arr release];
    [super dealloc];
    
}

//便利构造器
+(Car *)car
{
    Car *c = [[Car alloc]init];
    
    return [c autorelease];
    
}


// setter 方法
-(void)setArray:(NSMutableArray *)arr
{
    //防止 内存泄露
    if (_array != arr) {
        
        [_array release];
        
        _array = [arr retain];
   
    }
    
}

// getter 方法
-(NSMutableArray *)array
{
    [_array retain];
    
    return [_array autorelease];
}


//初始化 (重写父类方法)
- (instancetype)init
{
    self = [super init];
    if (self) {
        
        // 1. 成员变量
        
        // 两种写法 引用计数 + 1
        
        // 类的开始在init , 结束在dealloc 中, 成员变量在类中保持平衡
        _array = [[NSMutableArray alloc]init];
        
        _array = [[NSMutableArray array]retain];
        
        
        // 2. 属性 (引用计数保持平衡)(点方法会调用setter方法, 引用计数加1, 所以不能用alloc的初始化方法)
        
        self.arr = [NSMutableArray array];
        
        // 3. 如果把其他类写成属性 (引用计数保持平衡)
        
        self.stu =[[[Student alloc]init]autorelease];
        self.stu = [Student student]; // (便利构造器)

        
    }
    return self;
}



10.  cope : 所有遵循于NSCopying协议的类, 都可以使用copy

                 比如:  [NSString , NSArray,  NSDictionary, NSNumber, NSValue]   (NSString 特殊, 不可变也可以写copy)


11.  在系统类里面对不可变类型使用copy 那么其效果类似于 retain;

       不可变 : 使用copy, 会在原有基础上 + 1         = > 2


        NSArray *arr = [NSArray arrayWithObjects:@"1", @"2", nil];
        NSArray *arr1 = [arr copy];
        NSLog(@"arr= %p, arr1 = %p", arr, arr1);
        NSLog(@"retainCount: arr = %ld, arr1 = %ld", [arr retainCount], [arr1 retainCount]);

打印结果:  

arr= 0x10010eb10, arr1 = 0x10010eb10

retainCount: arr = 2, arr1 = 2


 // 由打印结果可以看出: 地址没有变化,  引用计数 + 1 变成 2


12.  可变对象使用copy得到的是不可变对象;    

       可变 :  使用copy, 会在结果上引用计数 + 1        = > 1

        NSMutableArray *mArr = [NSMutableArray arrayWithObjects:@"1", @"2", nil];
        NSMutableArray *mArr1 = [mArr copy];
        NSLog(@"mArr= %p, mArr1 = %p", mArr, mArr1);
        NSLog(@"retainCount: mArr = %ld, mArr1 = %ld", [mArr retainCount], [mArr1 retainCount]);

打印结果:

mArr= 0x10010ed30, mArr1 = 0x10010eee0

retainCount: mArr = 1, mArr1 = 1


// 由打印结果可以看出: 地址改变,  引用计数会在结果上的(mArr)引用计数 + 1 变成 1

  

13.  可变对象可以使用mutableCopy得到可变对象;


       NSMutableArray *mArr2 = [mArr mutableCopy];
        [mArr2 addObject:str];

14.  将属性写成 copy类型

建立Person类

.h

@property(nonatomic, copy)NSMutableArray *array;

.m  

// 系统的写法 写的还是copy
-(void)setArray:(NSMutableArray *)array
{
    if (_array != array) {
        [_array release];
        _array = [array copy]; // 变成不可变数组
    }
}

main.m

        People *p = [[People alloc]init];
        
        [p.array addObject:@"1"]; //不可变数组添加不了元素

// 运行一下, 就会crash, 需要将系统的setter方法进行改写

.m

// 重新写系统的方法, 把copy改成retain
-(void)setArray:(NSMutableArray *)array
{
    if (_array != array) {
        [_array release];
        _array = [array retain];
    }
}

main.m

        People *p = [[People alloc]init];
        
        [p.array addObject:@"1"];
        
        NSLog(@"p.array = %@", p.array);
 
        NSLog(@"retainCount = %ld", [p retainCount]);

打印结果:  


p.array = (

    1

)

retainCount = 1


15.  (1)如果在数组或字典(无论可变不可变)中添加一个元素,那么这个元素的引用计数+1(保证数组或字典在使用元素时安全)

   (2)如果在数组或字典(无论可变不可变)中移除一个元素,那么这个元素的引用计数-1,数组或字典释放时,其中的元素也一一释放掉

        //加入不可变数组
        Person *p1 = [[Person alloc ] init];
        NSLog(@"p1.retainCount = %ld", [p1 retainCount]);
        NSArray *array = [NSArray arrayWithObjects:p1, nil];
        NSLog(@"数组添加元素p1.retainCount = %ld", [p1 retainCount]);
       
        //加入可变数组
        Person *p2 = [[Person alloc ] init];
        NSLog(@"p2.retainCount = %ld", [p2 retainCount]);
        NSMutableArray *mArray = [NSMutableArray arrayWithObjects:
                                  p2, nil];
        NSLog(@"数组添加元素p2.retainCount = %ld", [p2 retainCount]);
        [mArray removeObject:p2];
        NSLog(@"数组移除元素p2.retainCount = %ld", [p2 retainCount]);

打印结果:  


p1.retainCount = 1

数组添加元素p1.retainCount = 2

p2.retainCount = 1

数组添加元素p2.retainCount = 2

数组移除元素p2.retainCount = 1


16.  assign : 不引起引用计数的改变 (只有简单类型才写成assign类型)

Person类

.h

@property (nonatomic, assign)  NSMutableDictionary *mDic;

.m

// 系统的写法
- (void)setMDic:(NSMutableDictionary *)mDic
{
    _mDic = mDic;
}



17. atomic : 属性安全, 通过线程队列来避免在同一时间对同一属性赋值产生冲突

      nonatomic : 非属性安全, 没有做冲突处理



  • 0
    点赞
  • 0
    收藏
    觉得还不错? 一键收藏
  • 0
    评论
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值