OC内存管理

    // 管理内存有三种方式
    // 1.垃圾回收,java常见的管理内存方法,系统来检测对象是否被使用,是否被释放
    // 2.MRC 手动管理引用计数,iOS管理内存的方式,程序员通过手动的方式来管理对象是否被释放
    // 3.ARC 自动管理引用计数,基于MRC,系统自动的管理内存,以后我们还是先使用MRC,培养管理内存的习惯
- (id)initWithName:(NSString *)name
               age:(NSInteger)age
{
    self = [super init];
    if (self) {
        self.name = name;
        self.age = age; // 对于整型变量来说完全不用考虑内存分配问题,所以它和_age = age完全相同
    // 对象创建之后,里面的数组也会创建好,不用在外面进行创建,避免因为忘了造成问题
        self.arr = [NSMutableArray array];
    }
    return self;
}
// boy.m
- (void)dealloc
{
    NSLog(@"对象被释放了");
    // 把成员变量里+1的操作全部减去
    [_name release];
    [_hobby release];
    [_girls release];
    [super dealloc];
}   

+ (Boy *)boy
{
    Boy *b = [[Boy alloc] init];
    // 写遍历构造器最后别忘了autorelease
    return [b autorelease];
}

+ (Boy *)boyWithName:(NSString *)name
               hobby:(NSString *)hobby
{
    Boy *b = [[Boy alloc] initWithName:name hobby:hobby];
    return [b autorelease];
}

- (id)copyWithZone:(NSZone *)zone
{
    Boy *b = [Boy allocWithZone:zone];
    b.hobby = self.hobby;
    b.name = _name;
    return b;
}

- (void)setHobby:(NSString *)hobby
{
    // 1.
    if (_hobby != hobby) {
        [_hobby release];
        _hobby = [hobby retain];
    }
    // 2.
    [hobby retain];
    [_hobby release];
    _hobby = hobby;
}
    Boy *boy = [[Boy alloc] init];
    Girl *girl = [[Girl alloc] init];

    // 对象被创建出来之后他的引用计数retainCount就变为1
    NSLog(@"%ld", boy.retainCount);
    // retain:对对象的引用计数进行+1操作 对象调用一次retain方法rC就加一
    [boy retain];
    NSLog(@"%ld", boy.retainCount);
    // 对对象的引用计数进行-1操作
    [boy release];
    NSLog(@"%ld", boy.retainCount);
    // 当对象的引用计数为1时,会自动调用dealloc方法,dealloc才是对应对象释放的方法
    [boy release];
    // 当对象调用release的时候,它的引用计数为1,这个对象就不在对它的引用计数进行-1操作,而是直接调用dealloc方法,所以我们在访问对象的引用计数还是1
    NSLog(@"%ld", boy.retainCount);
     // 过度释放,最常见的内存问题
    [boy release];
    [boy dealloc];
    NSArray *arr = @[@"1"];
    NSLog(@"%ld", arr.retainCount);
    NSString *str = @"1";
    // 不可变字符串地址在全局静态区,他的引用计数是-1,其他的对象都在堆区
    NSLog(@"%ld", str.retainCount);
    NSLog(@"%p", str);
    NSMutableString *str1 = [NSMutableString stringWithString:@"1"];
    NSLog(@"%ld", str1.retainCount);
    NSLog(@"%p", str1);
    NSDictionary *dic = @{@"1": @"2"};
    NSLog(@"%ld", dic.retainCount);

    NSLog(@"%ld", str1.retainCount);
    // release马上会把对象的引用计数-1,但是autorelease会延迟对对象的计数-1
    // 自动释放池
        @autoreleasepool {
        [boy autorelease];
        NSLog(@"%ld", boy.retainCount);
    }
    NSLog(@"%ld", boy.retainCount);
    // 内存管理的原则:加多少,对应减多少,加减做到平衡
    // 对象的所有权:拥有所有权的对象可以对他进行release
    Boy *boy1 = [Boy boy];
    [boy1 retain];
    NSLog(@"%ld", boy1.retainCount);
    [boy1 release];
    // 对象如果是我们进行alloc或者retain之后我们就获取了对象的所有权,就可以对对象进行release操作
    // 以后更推荐使用遍历构造器,下面是加上对对象进行释放这一步骤的正确做法
    // id是泛型指针,可以用在任何的方法中,但是instancetype代表实例类型,用在自定义初始化方法,便利构造器作为返回值类型使用,标识方法会返回一个对象回去
    NSArray *arr1 = [[NSArray alloc] initWithObjects:@"1", @"2", nil];
    [arr1 release];
    NSArray *arr2 = [NSArray arrayWithObjects:@"1", @"2", @"3", @"4", nil];
    NSLog(@"%ld", arr2.retainCount);
    // 签订协议第三步中设置代理人属性,其名字可随便设 不用必须用delegate
// boy.h
    // 4.引完头文件之后,boy需要签订协议
    @interface Boy : NSObject<GirlDelegate, NSCopying>
    // 系统的类要是实现copy拷贝的功能,必须先签订拷贝NSCopy的协议,然后实现对应的方法
    // mutableCopy出来的对象是可变的,copy出来的对象是不可变的
    // copy
    NSArray *newArr = [arr2 copy];  // retainCount == 2
//    NSArray *newArr = [NSArray arrayWithArray:arr2]; // retainCount == 1
    NSLog(@"%@", newArr);
    NSLog(@"%ld", newArr.retainCount);
    // copy也可以改变引用计数,但是它改变的是新对象的引用计数,而原先的对象计数不变


    // 不可变->可变
//    NSMutableArray *newArr1 = [NSMutableArray arrayWithArray:arr2];
    NSMutableArray *newArr2 = [arr2 mutableCopy]; // 同上边方法
    [newArr2 addObject:@"5"];
    NSLog(@"%@", newArr2);

    // 不可变的数组字典可以通过mutableCopy转换成可变的数组字典
    NSDictionary *dic = [NSDictionary dictionaryWithObjectsAndKeys:@"2", @"1", @"4", @"3", nil];
    NSMutableDictionary *muDic = [dic mutableCopy];
    NSLog(@"%@", muDic);

    // 如果自己的类想要实现copy的功能,就必须先签订NSCopying,然后实现对应的协议的方法,initWithZone,之后就可以使用copy的功能了
    Boy *boy = [Boy boyWithName:@"张阳阳" hobby:@"玩"];
    Boy *newBoy = [boy copy];
    NSLog(@"%@", newBoy.name);
    // 当对象放入到容器Array或者字典中,对象会被容器进行一次持有,就是retain一次,他的引用计数会加一,主要是为了防止空指针的问题
    // 等对象从容器中移除掉之后,相应的会-1
    Boy *boy1 = [[Boy alloc] init];
    [boy1 retain];
    [boy1 retain];
    NSLog(@"%ld", boy1.retainCount);
    NSMutableArray *arr = [NSMutableArray arrayWithObjects:boy1, nil];
    NSLog(@"%ld", [arr[0] retainCount]);
    [arr removeObjectAtIndex:0];
    NSLog(@"%ld", boy1.retainCount);
评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

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

抵扣说明:

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

余额充值