【iOS11.4】有必要将__weak修饰变量转化为__strong修饰变量

结论:在大量重复使用__weak修饰的变量时,把__weak修饰的变量赋值给__strong修饰的变量更好。

在每次使用__weak修饰变量时,编译器都会创建"objc_loadWeakRetained/objc_release"方法。比如下面示例代码:

    NSObject *obj = [[NSObject alloc] init];
    {
        id __weak obj1 = obj;
        NSLog(@"%@", obj1);
        NSLog(@"%@", obj1);
    }

在创建obj处打断点,查看汇编结果:

0x104346598 <+200>: bl     0x104346a90              ; symbol stub for: objc_initWeak
0x10434659c <+204>: ldr    x8, [sp, #0x30]
0x1043465a0 <+208>: str    x0, [sp, #0x28]
0x1043465a4 <+212>: mov    x0, x8
0x1043465a8 <+216>: bl     0x104346a9c              ; symbol stub for: objc_loadWeakRetained
0x1043465ac <+220>: mov    x1, x0
0x1043465b0 <+224>: mov    x8, sp
0x1043465b4 <+228>: str    x0, [x8]
0x1043465b8 <+232>: adrp   x0, 2
0x1043465bc <+236>: add    x0, x0, #0x98             ; =0x98
0x1043465c0 <+240>: str    x1, [sp, #0x20]
0x1043465c4 <+244>: bl     0x104346a30              ; symbol stub for: NSLog
0x1043465c8 <+248>: b      0x1043465cc              ; <+252> at ViewController.m:36
0x1043465cc <+252>: ldr    x0, [sp, #0x20]
0x1043465d0 <+256>: bl     0x104346ac0              ; symbol stub for: objc_release
0x1043465d4 <+260>: sub    x0, x29, #0x40            ; =0x40
0x1043465d8 <+264>: bl     0x104346a9c              ; symbol stub for: objc_loadWeakRetained
0x1043465dc <+268>: mov    x30, x0
0x1043465e0 <+272>: mov    x8, sp
0x1043465e4 <+276>: str    x0, [x8]
0x1043465e8 <+280>: adrp   x0, 2
0x1043465ec <+284>: add    x0, x0, #0x98             ; =0x98
0x1043465f0 <+288>: str    x30, [sp, #0x18]
0x1043465f4 <+292>: bl     0x104346a30              ; symbol stub for: NSLog
0x1043465f8 <+296>: b      0x1043465fc              ; <+300> at ViewController.m:37
0x1043465fc <+300>: ldr    x0, [sp, #0x18]
0x104346600 <+304>: bl     0x104346ac0              ; symbol stub for: objc_release
0x104346604 <+308>: sub    x0, x29, #0x40            ; =0x40
0x104346608 <+312>: bl     0x104346a84              ; symbol stub for: objc_destroyWeak

第一行调用objc_initWeak方法创建__weak修饰的变量obj1,下面我们使用了obj1变量进行了两次打印,可以看到每次打印之前调用了函数"objc_loadWeakRetained",打印之后又调用了函数"objc_release"。所以需要将__weak修饰变量转化为__strong修饰变量来减少编译器插入的"objc_loadWeakRetained/objc_release"函数对。

下面是将__weak转换为__strong的示例代码:

   NSObject *obj = [[NSObject alloc] init];
    id __weak obj1 = obj;
    {
        id __strong obj2 = obj1;
        NSLog(@"1 %@", obj2);
        NSLog(@"2 %@", obj2);
    }

编译结果为:

0x10fe7058d <+189>: call   0x10fe70994              ; symbol stub for: objc_initWeak
0x10fe70592 <+194>: mov    rdi, qword ptr [rbp - 0x78]
0x10fe70596 <+198>: mov    qword ptr [rbp - 0x80], rax
0x10fe7059a <+202>: call   0x10fe7099a              ; symbol stub for: objc_loadWeakRetained
0x10fe7059f <+207>: mov    qword ptr [rbp - 0x48], rax
0x10fe705a3 <+211>: mov    rsi, qword ptr [rbp - 0x48]
0x10fe705a7 <+215>: lea    rdi, [rip + 0x1af2]       ; @"1 %@"
0x10fe705ae <+222>: xor    ecx, ecx
0x10fe705b0 <+224>: mov    dl, cl
0x10fe705b2 <+226>: mov    al, dl
0x10fe705b4 <+228>: call   0x10fe70964              ; symbol stub for: NSLog
0x10fe705b9 <+233>: jmp    0x10fe705be              ; <+238> at ViewController.m:38
0x10fe705be <+238>: mov    rsi, qword ptr [rbp - 0x48]
0x10fe705c2 <+242>: lea    rdi, [rip + 0x1af7]       ; @"2 %@"
0x10fe705c9 <+249>: xor    eax, eax
0x10fe705cb <+251>: mov    cl, al
0x10fe705cd <+253>: mov    al, cl
0x10fe705cf <+255>: call   0x10fe70964              ; symbol stub for: NSLog
0x10fe705d4 <+260>: jmp    0x10fe705d9              ; <+265> at ViewController.m
0x10fe705d9 <+265>: lea    rdi, [rbp - 0x48]
0x10fe705dd <+269>: xor    eax, eax
0x10fe705df <+271>: mov    esi, eax
0x10fe705e1 <+273>: call   0x10fe709b8              ; symbol stub for: objc_storeStrong
0x10fe705e6 <+278>: lea    rdi, [rbp - 0x40]
0x10fe705ea <+282>: call   0x10fe7098e              ; symbol stub for: objc_destroyWeak

可以看到"objc_loadWeakRetained"方法只在最开始因为“id __strong obj2 = obj1;”操作而插入了一次,在下面打印过程中再也没有调用过。

©著作权归作者所有,转载或内容合作请联系作者
【社区内容提示】社区部分内容疑似由AI辅助生成,浏览时请结合常识与多方信息审慎甄别。
平台声明:文章内容(如有图片或视频亦包括在内)由作者上传并发布,文章内容仅代表作者本人观点,简书系信息发布平台,仅提供信息存储服务。

相关阅读更多精彩内容

  • 1.1 什么是自动引用计数 概念:在 LLVM 编译器中设置 ARC(Automaitc Reference Co...
    __silhouette阅读 10,717评论 1 17
  • Swift1> Swift和OC的区别1.1> Swift没有地址/指针的概念1.2> 泛型1.3> 类型严谨 对...
    cosWriter阅读 13,887评论 1 32
  • 他的轻狂留在某一节车厢 地下铁里的风比回忆还重 (光晞认识幕橙前对女孩儿的轻狂蛤) 整座城市一直等着我 有一段感情...
    苹果惜牛顿阅读 1,873评论 0 0
  • 工作是一种修行。 这是日本韬盛和夫在他的著作《活法》中的主要观点。 他说:“人哪里需要远离凡尘?工作场所就是修炼精...
    优祺和平阅读 5,045评论 0 0
  • 风吹的叶子瑟瑟 翘首过往的样子 还记得 初见似曾见诈是欢喜 你我并肩而立 好似亲密 风吹的叶子早已落完 再见不知曾...
    果冻果呐阅读 1,405评论 0 4

友情链接更多精彩内容