zoukankan      html  css  js  c++  java
  • iOS 内存管理之属性关键字

    你好2019!一起努力呀!

    主要分三种类型:

    1、原子操作相关: nonatomic、atomic

    nonatomic:非原子操作,对属性赋值的时候不加锁,多线程并发访问会提高访问效率

    atomic:原子操作,提供多线程安全,只在其相关的setter或getter方法的时候有加锁安全机制,其他的线程安全不负责

    属性默认的是原子操作,但是一般开发使用的是非原子操作。因为关于线程安全,只是依赖原子操作根本实现不了

    2、内存管理相关:assign、weak、copy、strong

    assign:修饰基础数据类型以及C数据类型

    weak:修饰OC对象,在对象被销毁的时候会被置为nil;(下面会对weak、__weak以及涉及到的弱引用计数表相关的进行个人理解)

    copy:一般用来修饰不可变类型对象以及block(关于blcok使用的关键字是从MRC的留下来的惯性关键字,在ARC上使用strong或copy均可,不过一般还是使用copy)他不会对原对象的引用计数发生变化,会生成新的地址。

    strong:修饰OC对象,尤其是可变类型的属性必须使用strong修饰,它不会生成新的内存地址,会使引用计数加1

    注意:

    2.1:

    关于weak、__weak、__strong修饰的对象

    例如:__weak weakObj = tempObj; 这个执行过程会触发到的主要方法objc_initWeak(id *location,id obj) -->storeWeak --->weak_register_no_lock

    其中location是指weakObj的地址,obj是指tempObj的地址(便于下边文字描述的理解)

    它通过对象的内存地址做为key,而对应的__weak修饰符变量的地址作为value注册到weak表中,在对像被销毁时,执行dealloc方法最终会调用weak_clear

    _no_lock方法,将这个对象对应的所有弱引用指针置为nil(objc_destroyWeak

    则是销毁该对象对应的value。当指向的对象被销毁时,会通过其内存地址,去weak表中查找对应的__weak修饰符变量,将其从weak表中删除)。所以weak在修饰只是让weak表增加了记录没有引起引用计数表的变化。

    __strong:当block内部执行异步操作的时候,__weak修饰的对象如果被释放掉,那么当内部的异步执行结束时用到weakObj的时候就不会崩溃,所以会在block内部使用__strong 将weakObj重新修饰,变为strongObj,因为strongObj属于局部变量,所以在block执行完毕之后跳出这个作用域strongObj会被释放,这个临时循环也会被打破。

    2.2:

    关于copy、strong 

    常见的问题是NSString为什么使用copy而不是strong关键字,

    简单说:NSString是不可变类型,,若其数据源是不可变类型,那么使用strong或copy效果都是一样的,若其数据源是可变类型的(例如NSString有一个可变的子类),当修改数据源的时候,使用copy修饰的字符串不会发生变化,但是使用strong修饰的会因为数据源的变化而变化。具体的情况,大家可以代码实验之!

    关于数组等对象的copy单层copy(也就是对整体是深copy,数组中的对象是浅copy)

    深copy、浅copy

    只有源对象是不可变类型且拷贝方式是copy, 是浅copy

    源对象是可变类型的时候无论拷贝方式是copy还是mutCopy,是深copy

    源对象是不可变类型,但其拷贝方式是mutCopy时,是深copy

    3、读写操作:readwrite、readonly(对应的setter 或 getter方法)

    readwrite 会有其对应的setter和getter方法

    readonly只有getter方法

    4、其他关键字:@dynamic、@synthesize

    被@dynamic,修饰的关键字,系统不会在生成其对应的setter 和 getter方法实现,也就是代码使用点语法的时候不会报错,但是执行赋值或取值的操作会崩溃(以为找不到相关的方法实现)

    被@synthesize修饰的属性:个人理解是对属性对应的成员变量 重命名。属性默认的成员变量是在属性的前面加下划线,我们可以使用@synthesize进行重命名。并且@synthesize修饰的属性编译器会自动添加setter getter方法(当然不是用@synthesize关键字修饰,目前也是编译器自动添加的)

    5、程序分区:从高地址到低地址排序

    5.1:栈(先进后出)

    栈的大小在编译时就已经确定了,一般是2M;栈是一块从高到低地址的连续区域。由编译器自动分配并释放,存放函数的参数值,局部变量等。栈是系统数据结构,对应线程/进程是唯一的。优点是快速高效,缺点时有限制,数据不灵活。

    栈空间分静态分配 和动态分配两种。 

    静态分配是编译器完成的,比如自动变量(auto)的分配。
    动态分配由alloca函数完成。 

    栈的动态分配无需释放(是自动的),也就没有释放函数。

    为可移植的程序起见,栈的动态分配操作是不被鼓励的。

    5.2:堆(先进先出)

    堆是从低到高地址的不连续区域,分配方式类似链表;存储的为malloc , new ,alloc出来的对象。堆获得的空间比较灵活,也比较大。一般速度比较慢,容易产生碎片。

    这部分的内存管理是要开发者自己管理控制的。

    5.3:全局/静态

    存放静态/全局变量;全局区细分为未初始化/初始化区。

    5.4:常量

    存放常量;程序中使用的常量会到常量区获取。

    5.5:代码

    存放二进制代码,运行程序就是执行代码,代码要执行就要加载进内存(RAM运行内存)。

    遗留问题:

    autoreleasePool

    __unsafe_retained

    __antoreleasing

    这些相关的理解!

    下次分析整理。。。。。。

    其他相关连接:

    关于堆栈相关的理解:https://www.jianshu.com/p/8588981a74de 

  • 相关阅读:
    linux基础命令之一
    Chrome 控制台使用大全
    移动端效果 — 页面引入在线视频
    移动端——简单计分表单
    JS操作cookie
    移动端页面字体——rem的使用
    Highcharts 使用总结
    CSS水平居中
    python学习 day2
    python学习 day1
  • 原文地址:https://www.cnblogs.com/lisaloveyou1900/p/10204946.html
Copyright © 2011-2022 走看看