iOS学习笔记-----内存管理初探

一.OC内存管理的概念

1.OC内存管理的概念:管理OC对象的生命周期
2.内存管理的方法:
(1)alloc new copy会从内存中分配空间,封装malloc,是对象生命周期的起始(alloc new copy是NSObject的方法);
(2)dealloc方法是销毁对象用的,封装了free,是对象生命周期的结束,但是并不是自己调用的;
(3)retain-持有 release-释放 retainCount:引用计数
3.僵尸对象:在内存空间被系统回收之后,那个实例就叫僵尸对象
4.野指针(变量):调用这个僵尸对象的指针就叫野指针
5.内存管理的原则:谁retain,谁release
使用alloc申请内存,那么对象的引用计数为1
MRR(手动内存管理模式)要调用retain方法,才会让p2持有p1,引用计数+1;release 是用引用计数-1;

二.设置器方法的内存管理

- (void)setDog:(Dog *)dog {

    //判断是否进行自我赋值,如果不是则进行内存管理,如果是则不需要做任何事,避免野指针变量的出现
    //这个if判断也更加符合业务逻辑

   if(_dog != dog) {

       // 旧狗释放
        [_dogrelease];
        // 新狗retain
       _dog = [dog retain];
    }
}

三.@property的使用

@property就是一个代码生成机制

@property(atomic, retain) Car *car;
@property(atomic, retain, readwrite)NSString *name;
@property(nonatomic,assign, getter = aa,setter = bb:) NSInteger age;

第一类

1.retain 其他的—包括自己定义的类
2.copy 涉及到NSString NSSet NSArray NSDicitonary这些类(共同点:都有可变的子类),都用copy关键字修饰
3.assign(默认)所以涉及到基本数据类型,都用assign关键字修饰
4.copy与retain的区别:copy是完完整整的复制一遍实例,除了retainCount

第二类

1.readonly :代表设置器方法并没有被生成
2.readwrite :设置器方法和返回器方法都被生成

第三类

1.atomic: 多线程保护机制,会耗用更多的系统资源
2.nonatomic: 没有多线程保护机制,容易失控,所以自己写多线程,不要使用多线程操作

第四类

可以重命名设置器和返回器方法,并且原来的方法还是在的
setter = bb: getter = aa

四.copy

copy是将实例除了retainCount,在堆区复制了一遍(新的一块内存),并且有一个指针指向这个内存的首地址.
当属性类型为NSString NSSet NSArray NSDicitonary内存管理方式采用copy.

        NSMutableString *mStr = [NSMutableStringstringWithString:@"xiaohua"];
         p1.name = mStr;
       NSLog(@"p1的名字:%@", p1.name);
        [mStrappendString:@"gual"];
        // 如果使用retain,则名字会被修改,不符合逻辑. 使用copy,则不会,因为是两块内存.
       NSLog(@"p1的名字:%@", p1.name);

五.自动释放池

1.自动释放池的作用:

(1)将对象加入到自动释放池中,就不需要再关注对象的release.
(2)当自动释放池被销毁时,会对里面的对象逐个release.

2.autorelease:

(1)返回实例对象本身.
(2)调用了autorelease之后,对象本身的引用计数是不变.

3.自动释放池的优点:

程序猿不必再关心对象的释放

4.自动释放池的缺点:

占用较大的对象如果使用autorelease,会浪费系统资源

5.自动释放池的存储:

(1)自动释放池以栈结构(先进后出)进行存储,当一个对象调用autorelease方法时,会将这个对象放入到栈顶的自动释放池.
(2)自动释放池,是用一个数组来管理加入的实例,加入的时候实际上是调用 addobject.

int main(int argc, const char * argv[]) {

    // 自动释放池,当左边大括号开始的时候,自动释放池就被创建,右边大括号结束的时候,自动释放就被销毁了
    @autoreleasepool {

        Person *p1 = [[[[Person alloc] init] autorelease] autorelease];
        p1.age = 21;

        @autoreleasepool {

            Person *p2 = [[[Person alloc] init] autorelease];
            p2.age = 22;

        }

        Person *p3 = [[[Person alloc] init] autorelease];
        p3.age = 23;


     }

六.ARC模式

1.ARC的作用

ARC是编译器特性,也就是在代码编译之后,编译器自动帮你加上retain release

2.ARC的原则

(1)当没有一个强指针指向实例的时候,实例就要被销毁
(2)不允许 手动调用 retain, release, autorelease, retainCount ,[super dealloc] ,只有copy是可以的
(3)在ARC环境可以把对象添加到自动释放池中

 __autoreleasing Person *p1 = [[Person alloc] init]

3.strong与weak

(1)__strong :修饰的指针变量为强指针变量
(2)__weak :弱指针变量
在@property里使用关键字

  • strong 就相当于WRR里的retain

  • weak 就相当于WRR里的assign

  • copy 和MRR里的copy是一样的

 // @property使用关键字strong之后生成的设置器方法
(void)setDog:(__strong Dog *)dog {


    if (_dog != dog) {

        _dog = dog;
    }
}
// @property使用weak关键字后生成的设置器方法
- (void)setPerson:(__weak Person *)person {

    if(_person != person) {

        _person = person;
    }
}

ARC不是万能的,还是会造成循环引用

七.循环引用

对象A retain(strong)对象B。同时对象B retain(strong)对象A, 这种情况我们称之为循环引用·循环引用会导致两个对象都无法销毁掉。
解决方法:其中一个对象使用assign(weak).

八.ARC、MRR的使⽤用标记

对于某些我们不希望使用 ARC 的文件,例如第三方库源文件,可以在 Project Settings -> Build Phases 中设置
-fno-objc-arc 标记源代码文件使用MRR
-fobjc-arc 标记源代码文件使用ARC

你可能感兴趣的:(iOS学习笔记)