OC内存管理2与OC闭包初步|青训营笔记

105 阅读3分钟

这是我参与「第四届青训营 」笔记创作活动的的第4天

浅拷贝与深拷贝

浅拷贝:仅拷贝指针,复制一个指针,指向同一块内存区域,实际内存并没有发生拷贝

深拷贝:内容拷贝,拷贝数据到新的一块内存区域,指针指向拷贝的数据区

可变对象与不可变对象的拷贝行为——以NSString为例

1.The address of [NSString copy] is the same as NSString

While the address of [NSString mutableCopy]  is different from NSString

对于NSString复制是浅拷贝,可变复制是深拷贝

2.The address of [NSMutableString copy]&[NSMutableString mutableCopy] are different from  NSString

对于NSMutableString(可变对象)两种拷贝方式都是深拷贝,而[NSMutableString copy]本质是在内存里创建了一个NSString对象, [NSMutableString mutableCopy]本质是在内存里创建了一个NSMutableString的对象

3.Summary:代码中,深拷贝在转换可变对象与不可变对象中常常用到

@property权限修饰下的拷贝行为

对于@propertry copy修饰下的NSString 无论是哪一种拷贝 地址都相同

代码中一般用copy修饰不可变对象,防止传入NSMutableString不管传入对象是可变的还是不可变的,都可以保证自己持有的是不可变的副本,初始化后不会被外部修改所影响

Strong只是强指针的指向

闭包与Objective-C block

计算机语言中、 “闭包(Closure) 是由函数和与其相关的引用环境组合而成的实体。”

Block是OC语言对闭包的实现,闭包除具备“函数和函数指针”的所有功能外, 还包括声明它的上下文(如作用域内的自由变量等)。

block基础

block是闭包在Objective-C中的实现

Block可以接受参数,也可以有返回值

Block可以分配在栈&堆上,也可以是全局的。分配到栈上的块可以拷贝到堆中,与标准的Objective-C对象一样,具备引用计数

Block的标准格式:returnType (^blockName)(Paras);

^returnType(parameters){

//do the service logic

};

Eg:int (^sumBlock) (int a, int b) =^int(int a, int b) {

return a+B;//简便写法

}

Int sum = sumBlock(1,1)//调用

进一步简便

Void (^printBlock)(void) =^{

NSLog{@“Hello World!”};

}; 

Block的typedef

typedef returnType (^blockName)(parameters);

Eg:

image.png

Block的内存管理

在Objective-C语言中,一共有3种类型的block:

1、_NSConcreteGlobalBlock 保存在text段的全局的静态block,不会访问任何外部变量。

2、_NSConcreteStackBlock 保存在栈中的block,当函数返回时会被销毁。

3、_NSConcreteMallocBlock 保存在堆中的block,当引用计数为0时会被销毁。(ARC)

!注意block循环引用问题

在block内直接调用类的实例变量会使self(类的实例)引用计数加1, 这样可能会引起循环引用问题(可以用__weak或local-var处理);

  • 变量捕获

  1. Block的值引用,对于普通c变量在block的引用,是获取在初始化时的c变量值,在block初始化定义之后出现的值的改变不影响block方法调用的结果。
  2. Block的名称引用,对于普通c变量若由__block关键字修饰,则是名称引用,即在方法调用之前所有的变量值的修改都会影响;捕获对象的属性@property(nonatomic,copy)NSString *name
  3. Block的循环引用例子与解决见图

image.png

image.png