内存管理

//
//  main.m
//  02-引用计数器使用
//

#import <Foundation/Foundation.h>
/**
内存管理分类:ARC(自动内存管理) 和MRC (手动内存管理)

 ARC:内存管理的事情有系统来做
 MRC: 内存管理的事情由程序员来做

 要想手动管理内存,先要将程序变成手动内存管理状态
 */
/**
 retain 使引用计数+1
 release 使引用计数 -1  
 alloc/copy/new 都会使引用计数 +1  ,但是只用于创建对象
 retainCount :记录引用计数器的值

 注意:内存的法则:引用计数有+1就要有-1,保持平衡。

 //当一个对象的retainCount值为0的时候,即被释放的时候,系统会调用dealloc方法
 */

#import "Person.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        //刚开始创建,默认的retainCount == 1;
        Person *person = [[Person alloc]init];

        NSLog(@"%lu",[person retainCount]);

        //发送retain消息,retainCount +1   ==2
        [person retain];
        NSLog(@"%lu",[person retainCount]);
        //发送release消息,是retainCount -1  ==1
        //[person release];
        //当retainCount的值为0时,无法打印retainCount的0值
        //此时的person对象是僵尸对象,不能调用方法。
        //野指针:指向僵尸对象的指针
        //空指针:保存的时nil
        //给对象发送release消息,并不代表释放对象,只是使retainCount-1.
        //释放对象是当对象的retainCount==0的时候

        NSLog(@"%lu",[person retainCount]);
        [person eat];
        //retainCount == 0
        [person release];
    }
    return 0;
}

//
//  main.m
//  copy
//
#import <Foundation/Foundation.h>
int main(int argc, const char * argv[])
{
    @autoreleasepool {
        /**
         *  copy,mutablecopy
         注意:首先要遵守copy,mutablecopy相关的协议(NSCoping,NSMutbaleCoping)。
         2.nsstring等已经遵守了这个协议了,所以可以直接使用,但是自定义的类,就要先去遵守并实现相关协议。
         */

        NSString *string1 = @"good for you";
        //将原字符串,拷贝了一份,放到了一个新开辟的空间。这个新的字符串是可变的   -- 通过mutableCopy得到的是可变字符串
        NSMutableString *mutString1  = [string1 mutableCopy];

        NSLog(@"%@,%@",string1,mutString1);

        [mutString1 setString:@"OK"];

         NSLog(@"%@,%@",string1,mutString1);
        //将原字符串,拷贝一份,放到一个新的空间。这个新的字符串是不可变的。
        //通过copy得到的时不可变字符串
        NSString *newString = [mutString1 copy];

        newString = @"iOS";

        NSLog(@"%@,%@,%@",string1,mutString1,newString);
    }
    return 0;
}

//
//  main.m
//  07-自动释放池
//

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[])
{
    /**
     自动释放池:一个程序可以有很多个自动释放池。自动释放池是可以嵌套的
     在嵌套的自动释放池当中创建的对象会以当前的自动释放池为参考进行操作。
     */
    //旧版本的
    NSAutoreleasePool *pool = [[NSAutoreleasePool alloc]init];

    [pool release];
    //[pool drain];

    //新版本的自动释放池
    @autoreleasepool {

        @autoreleasepool {

            @autoreleasepool {

            }
        }

        Person *person = [[Person alloc]init];
        //当给一个对象发送autorelease消息的时候,系统会讲对象放入当前的自动昂释放池的一个数组当中
        [person autorelease];
        //[person release];

    }//当当前的自动释放池结束的时候,他会给里面的每个对象发送release消息

    //使用自动释放池原因:因为有的时候创建的对象不便于立即释放,所以给他么发送autorelease消息,到自动释放池结束的时候一起释放
    return 0;
}

//
//  main.m
//  09-NSArray
//

#import <Foundation/Foundation.h>
#import "Person.h"
int main(int argc, const char * argv[])
{

    @autoreleasepool {
        //不要拿数组,字典的retaincount值做一些事情(判断对象的所有者个数)
        NSMutableArray *mutArray = [[NSMutableArray alloc]init];

        NSLog(@"%lu",mutArray.retainCount);

        [mutArray addObject:@"11"];

        Person *person = [[Person alloc]init];

        //数组的addObject:方法在使用的时候,会给元素自动给的引用计数+1
        [mutArray addObject:person];

        [person release];

        [mutArray release];

    }
    return 0;
}