mirror of
https://github.com/NohamR/knowledge-kit.git
synced 2026-05-25 04:17:17 +00:00
docs: image url
This commit is contained in:
@@ -28,7 +28,7 @@ block(1, 2);
|
||||
|
||||
用指令`xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转为 c++
|
||||
|
||||
<img src="./../assets/BlockViaClangC.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockViaClangC.png" style="zoom:25%">
|
||||
|
||||
`ViewController.m` 的 `viewDidLoad` 函数为 `_I_ViewController_viewDidLoad`
|
||||
|
||||
@@ -240,7 +240,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
|
||||
}
|
||||
```
|
||||
|
||||
<img src="./../assets/MockBlockDemo.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MockBlockDemo.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -254,7 +254,7 @@ struct __ViewController__viewDidLoad_block_desc_0 {
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/block-structure.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-structure.png" style="zoom:40%">
|
||||
|
||||
|
||||
|
||||
@@ -279,11 +279,11 @@ printBlock();
|
||||
|
||||
用 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
|
||||
|
||||
<img src="./../assets/SimpleBlockExploreDemo.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleBlockExploreDemo.png" style="zoom:40%">
|
||||
|
||||
概括如下:
|
||||
|
||||
<img src="./../assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/SimpleSimpleBlockCaptureStructure.png" style="zoom:40%">
|
||||
|
||||
|
||||
|
||||
@@ -301,7 +301,7 @@ printAgeBlock();
|
||||
|
||||
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
|
||||
|
||||
<img src="./../assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/AutoVariableCaptureByBlock.png" style="zoom:25%">
|
||||
|
||||
代码分析:
|
||||
|
||||
@@ -338,7 +338,7 @@ printInfoBlock();
|
||||
|
||||
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
|
||||
|
||||
<img src="./../assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StaticVariableCaptureByBlock.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -379,7 +379,7 @@ age is 28, height is 176
|
||||
|
||||
用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++ 代码
|
||||
|
||||
<img src="./../assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/GlobalVariableWillNotCaptureByBlock.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -460,7 +460,7 @@ block 截获变量可以分为:
|
||||
|
||||
用指令 `xcrun --sdk iphoneos clang -arch arm64 Person.m -rewrite-objc -o Person-arm64.cpp` 转换为 c++ 代码
|
||||
|
||||
<img src="./../assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockWillCaptureMethodSelfVariable.png" style="zoom:25%">
|
||||
|
||||
|
||||
|
||||
@@ -582,13 +582,13 @@ static void __Person__testBlockCapture_block_func_0(struct __Person__testBlockCa
|
||||
|
||||
我们知道 block 可以看成是一个 oc 对象,所以它有类型,写个 Demo1 验证下
|
||||
|
||||
<img src="./../assets/BlockClassType.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockClassType.png" style="zoom:40%">
|
||||
|
||||
也就是说: `__NSGlobalBlock__` -> `NSBlock` -> `NSObject`。
|
||||
|
||||
继续验证,Demo2
|
||||
|
||||
<img src="./../assets/OCBlockType.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCBlockType.png" style="zoom:40%">
|
||||
|
||||
同时利用指令 `xcrun --sdk iphoneos clang -arch arm64 ViewController.m -rewrite-objc -o ViewController-arm64.cpp` 转换为 c++
|
||||
|
||||
@@ -613,7 +613,7 @@ block 的类型可以通过 isa 或者 class 方法查看,最终都是继承
|
||||
|
||||
这3种 block 在内存中的排布如下图:
|
||||
|
||||
<img src="./../assets/block-memorylayout.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-memorylayout.png" style="zoom:40%">
|
||||
|
||||
|
||||
|
||||
@@ -625,7 +625,7 @@ Demo:
|
||||
|
||||
由于 ARC 默认会做一些优化,为了彻底的研究 block,我们将工程的 ARC 关掉(Build Setting 里 Automatic Reference Counting 设置为 No)
|
||||
|
||||
<img src="./../assets/OCStackBlockCrash.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/OCStackBlockCrash.png" style="zoom:30%">
|
||||
|
||||
分析:
|
||||
|
||||
@@ -643,7 +643,7 @@ Demo:
|
||||
|
||||
当 `__NSStackBlock__` 调用 `copy` 方法后会变为 `__NSMallocBlock__`。如下图:
|
||||
|
||||
<img src="./../assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/FixStackBlockIssueWithCopy.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -699,7 +699,7 @@ int main(int argc, const char * argv[]) {
|
||||
|
||||
MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也就是栈上定义的 block,函数调用结束后可能一些相关数据就释放了,存在潜在风险。
|
||||
|
||||
<img src="./../assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockAsFunctionReturnValueIsDangerous.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -707,7 +707,7 @@ MRC 下 block 作为函数的返回值是比较危险的。在方法内部,也
|
||||
|
||||
MRC 下如果函数返回值是 block,且 block 内做了 auto 变量捕获的逻辑,编译器会报错:`Returning block that lives on the local stack`。此时 block 应该为 `__NSStackBlock__`
|
||||
|
||||
<img src="./../assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCCompileFailedWhenBlockCaptureAutoVarsiableAndAsReturnValue.png" style="zoom:30%">
|
||||
|
||||
即使编译器不报错,也存在很大风险,因为 block 创建在栈上,函数返回后栈内存可能被回收,导致后续访问野指针。
|
||||
|
||||
@@ -738,7 +738,7 @@ HelloBlock generateBlock(void) {
|
||||
|
||||
另外的改法是,在 Build Setting 中改为 ARC,看看
|
||||
|
||||
<img src="./../assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/CompileWillCallCopyWhenBlockCaptureAutoVarsiableAndAsReturnValueInARC.png" style="zoom:30%">
|
||||
|
||||
也就是说,ARC 模式下,当 block 捕获了 auto 变量,并且作为函数返回值的时候,ARC 会自动调用 copy 方法,将 `__NSStackBlock__` 变为 `__NSMallocBlock__`
|
||||
|
||||
@@ -819,11 +819,11 @@ ARC 下:如果 block 调用 copy 方法,则 block 仍旧为 `__NSMallocBloc
|
||||
|
||||
MRC 下,栈内捕获了 auto 变量的 block 为 `__NSStackBlock__`
|
||||
|
||||
<img src="./../assets/LocalBlockInMRC.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInMRC.png" style="zoom:30%">
|
||||
|
||||
改为 ARC
|
||||
|
||||
<img src="./../assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/LocalBlockInARCWillCallCopy.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -862,31 +862,31 @@ dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(1 * NSEC_PER_SEC)), di
|
||||
|
||||
ARC 下:block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,捕获的对象将会在 block 销毁后销毁
|
||||
|
||||
<img src="./../assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCObjectWillReleasedWhenLeaveScope.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
MRC 下:block 对象捕获了 auto 外部变量,是一种 `__NSMallocBlock__`,因为是 MRC,所以需要手动管理内存。会发现对象将在离开作用域后立马销毁,不会被 block 所捕获。
|
||||
|
||||
<img src="./../assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectCannotCaptureByMallocBlock.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
MRC,对 block 加 copy,变为 `__NSMallocBlock__` 呢?
|
||||
|
||||
<img src="./../assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/MRCObjectWillReleaseWhenBlockIsReleased.png" style="zoom:30%">
|
||||
|
||||
ARC 下对 block 引用的对象加 `__weak` 修饰呢?
|
||||
|
||||
<img src="./../assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ARCWeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
|
||||
|
||||
用指令 `xcrun --sdk iphoneos clang -arch arm64 main.m -rewrite-objc -fobjc-arc -fobjc-runtime=ios-8.0.0 -o main-arm64.cpp` 转换为 c++ 进行分析看看。注意,因为 weak 涉及运行时,需要在 clang 后添加 runtime 参数
|
||||
|
||||
<img src="./../assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectCapturedByBlock.png" style="zoom:30%">
|
||||
|
||||
如果对 Person 不加 `__weak` 修饰,block 结构体内部将会是`__strong`。
|
||||
|
||||
<img src="./../assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/StrongObjectCapturedByBlock.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -930,13 +930,13 @@ static void __main_block_dispose_0(struct __main_block_impl_0*src) {_Block_objec
|
||||
|
||||
Demo1:
|
||||
|
||||
<img src="./../assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/ObjectWillReleaseWhenGCDTimeout.png" style="zoom:30%">
|
||||
|
||||
说明:ARC 环境下,GCD 的 block 会自动被拷贝到堆上 `__NSMallocBlock__`,堆上的 block 会对使用的对象进行 copy,所以 person 引用计数+1,则在 GCD block 执行完毕后才 release
|
||||
|
||||
Demo2
|
||||
|
||||
<img src="./../assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakObjectWillReleaseWhenLeaveScope.png" style="zoom:30%">
|
||||
|
||||
- 栈空间上的 block 是不会对对象进行保命的(不管是 ARC 还是 MRC,都不调用 retain、copy 方法)。
|
||||
- ARC 下, block 如果访问了 auto, static 变量,则属于 `__NSStackBlock__`,ARC 下用强指针指向,则会变为 `__NSMallocBlock__ 堆上的 block, 是会对对象进行保命的。GCD 的 block 会自动拷贝到堆上,属于 `\__NSMallocBlock__`,也会对对象进 行 copy 保命。
|
||||
@@ -950,13 +950,13 @@ Demo2
|
||||
|
||||
Demo3
|
||||
|
||||
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterTotalTime.png" style="zoom:30%">
|
||||
|
||||
因为 GCD 是给 MainQueue 添加任务的,所以是串行,2个任务前后按照3s、1s 后打印。由于最晚的一个任务是访问强指针对象,所以不会释放。等到 GCD 全部执行完后,Person 才释放。
|
||||
|
||||
Demo4
|
||||
|
||||
<img src="./../assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/DoubleGCDMainQueueTaskObjectWillReleaseAfterStrongReference.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -1130,7 +1130,7 @@ test 和 test2 的本质区别
|
||||
|
||||
Demo3
|
||||
|
||||
<img src="./../assets/VisitReleasedStackBlockWillCrash.png" style="zoom:30%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/VisitReleasedStackBlockWillCrash.png" style="zoom:30%" />
|
||||
|
||||
为什么上面的代码会 crash?
|
||||
|
||||
@@ -1195,7 +1195,7 @@ Demo3
|
||||
|
||||
Demo4
|
||||
|
||||
<img src="./../assets/BlockAssignIsValueAssign.png" style="zoom:30%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockAssignIsValueAssign.png" style="zoom:30%" />
|
||||
|
||||
分析:
|
||||
|
||||
@@ -1391,7 +1391,7 @@ MyBlock block = ^{
|
||||
|
||||
转为 C++
|
||||
|
||||
<img src="./../assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__Block.png" style="zoom:30%">
|
||||
|
||||
```c++
|
||||
struct __Block_byref_age_0 {
|
||||
@@ -1435,7 +1435,7 @@ block 内部的函数在修改 age 的时候其实就是通过 `__main_block_imp
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/block-forwarding.png" style="zoom:40%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-forwarding.png" style="zoom:40%">
|
||||
|
||||
|
||||
|
||||
@@ -1447,7 +1447,7 @@ QA:为什么`__block` 变量的 `__Block_byref_age_0` 结构体并不在 block
|
||||
|
||||
看个有趣的例子,验证下 __block 的效果
|
||||
|
||||
<img src="./../assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block__BLOCKAssignObject.png" style="zoom:30%" />
|
||||
|
||||
转换成 c++ 可以看到
|
||||
|
||||
@@ -1492,7 +1492,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
|
||||
|
||||
对` __block` 修饰的对象,clang 转换为 c++ 后如下:
|
||||
|
||||
<img src="./../assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeVariableUse__BlockOnObject.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -1505,7 +1505,7 @@ __attribute__((__blocks__(byref))) __Block_byref_num2_0 num2 = {(void*)0,(__Bloc
|
||||
|
||||
注意:
|
||||
|
||||
<img src="./../assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/NSMutableArrayDonotNeedBlockToUseArray.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
@@ -1575,7 +1575,7 @@ int main(int argc, const char * argv[]) {
|
||||
|
||||
我们将断点设置到 NSLog 这里,打印出自定义结构体 `__main_block_impl_0` 中的 age 。
|
||||
|
||||
<img src="./../assets/Block-variableAddress.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/Block-variableAddress.png" style="zoom:30%">
|
||||
|
||||
```c
|
||||
// 0x0000000105231f70
|
||||
@@ -1750,7 +1750,7 @@ in block: age = 28, address is 0x600000464938
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/BlockChangeOuterValue.png" style="zoom:100%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockChangeOuterValue.png" style="zoom:100%">
|
||||
|
||||
分析:
|
||||
|
||||
@@ -1804,7 +1804,7 @@ in block: age = 28, address is 0x600000464938
|
||||
|
||||
通过 Demo1 和 Demo2 总结下:` __forwarding` 的作用是什么?为什么这么设计
|
||||
|
||||
<img src="./../assets/block_forwarding.png" style="zoom:15%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block_forwarding.png" style="zoom:15%">
|
||||
|
||||
|
||||
|
||||
@@ -1903,7 +1903,7 @@ Tips:实现 block 拷贝及其捕获对象的函数是 `_Block_copy`,工作
|
||||
|
||||
Demo0
|
||||
|
||||
<img src="./../assets/BlockVariableDemo0.png" style="zoom:100%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo0.png" style="zoom:100%">
|
||||
|
||||
可以看到:
|
||||
|
||||
@@ -1912,17 +1912,17 @@ Demo0
|
||||
|
||||
Demo1
|
||||
|
||||
<img src="./../assets/BlockVariableDemo1.png" style="zoom:100%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo1.png" style="zoom:100%">
|
||||
|
||||
<img src="./../assets/block-strong-object-memoery.png" style="zoom:30%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-strong-object-memoery.png" style="zoom:30%">
|
||||
|
||||
|
||||
|
||||
Demo2
|
||||
|
||||
<img src="./../assets/BlockVariableDemo2.png" style="zoom:100%">
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/BlockVariableDemo2.png" style="zoom:100%">
|
||||
|
||||
<img src="./../assets/block-weak-object-memoery.png" style="zoom:30%" >
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/block-weak-object-memoery.png" style="zoom:30%" >
|
||||
|
||||
|
||||
|
||||
@@ -2121,7 +2121,7 @@ __attribute__((__blocks__(byref))) __Block_byref_p_0 p = {
|
||||
|
||||
看个 Demo
|
||||
|
||||
<img src="./../assets/blockCaptureStrongObjectError.png" style="zoom:40%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/blockCaptureStrongObjectError.png" style="zoom:40%" />
|
||||
|
||||
可以看到 block 放在堆上的时候(被抢指针指向、作为返回值)的时候,如果 block 内部访问了强指针指向的对象,则会发生循环引用。
|
||||
|
||||
@@ -2164,7 +2164,7 @@ Person *p = [[Person alloc] init];
|
||||
|
||||
|
||||
|
||||
<img src="./../assets/WeakSolveBlockRetainCycle.png" style="zoom:40%" />
|
||||
<img src="https://raw.githubusercontent.com/FantasticLBP/knowledge-kit/master/assets/WeakSolveBlockRetainCycle.png" style="zoom:40%" />
|
||||
|
||||
|
||||
|
||||
@@ -2186,7 +2186,7 @@ p.block();
|
||||
|
||||
`__unsafe_retained` 因为不安全所以不推荐,`__block` 因为使用繁琐,且必须等到调用 block 才会释放内存,所以不推荐。ARC 下最佳用 `__weak`
|
||||
|
||||

|
||||

|
||||
|
||||
|
||||
|
||||
|
||||
Reference in New Issue
Block a user