【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;”操作而插入了一次,在下面打印过程中再也没有调用过。

你可能感兴趣的:(【iOS11.4】有必要将__weak修饰变量转化为__strong修饰变量)