博客> OC 对象本质
OC 对象本质
2019-08-18 12:33 评论:0 阅读:294 BellaWong
alloc init本质

OC对象本质

如下代码:

TLperson *p = [TLperson alloc];
p.age = 20;
TLperson *p1 = [p init];
TLperson *p2 = [p init];
NSLog(@"\n%@\n%@\n%@",p,p1,p2);

控制台打印:  1.png

结论:init其实什么也没有,对象的初始化是alloc做的,init其实是为了给我们进行重载的。 objc源码地址: https://opensource.apple.com/tarballs/objc4/

使用LLBD查看汇编代码,可以在汇编跳转[TLperson alloc]函数处下一个符号断点,就能看到alloc的内部实现 libobjc.A.dylib`+[NSObject alloc]: -> 0x10dc4b179 <+0>: jmp 0x10dc49fd6 ; _objc_rootAlloc

objc源码可以看到alloc就跳转到了_objc_rootAlloc这个函数 进入函数内部,_objc_rootAlloc内部实现如下:

libobjc.A.dylib`_objc_rootAlloc:
->  0x1c8c4ee9c <+0>:   stp    x20, x19, [sp, #-0x20]!
    0x1c8c4eea0 <+4>:   stp    x29, x30, [sp, #0x10]
    0x1c8c4eea4 <+8>:   add    x29, sp, #0x10            ; =0x10 
    0x1c8c4eea8 <+12>:  mov    x19, x0
    0x1c8c4eeac <+16>:  ldr    x8, [x19]
    0x1c8c4eeb0 <+20>:  and    x8, x8, #0xffffffff8
    0x1c8c4eeb4 <+24>:  ldr    x8, [x8, #0x20]
    0x1c8c4eeb8 <+28>:  and    x8, x8, #0x7ffffffffff8
    0x1c8c4eebc <+32>:  ldrb   w8, [x8, #0x2]
    0x1c8c4eec0 <+36>:  tbz    w8, #0x0, 0x1c8c4eee0     ; <+68>
    0x1c8c4eec4 <+40>:  mov    x0, x19
    0x1c8c4eec8 <+44>:  mov    x1, #0x0
    0x1c8c4eecc <+48>:  bl     0x1c8c4451c              ; class_createInstance
    0x1c8c4eed0 <+52>:  cbz    x0, 0x1c8c4eefc          ; <+96>
    0x1c8c4eed4 <+56>:  ldp    x29, x30, [sp, #0x10]
    0x1c8c4eed8 <+60>:  ldp    x20, x19, [sp], #0x20
    0x1c8c4eedc <+64>:  ret    
    0x1c8c4eee0 <+68>:  adrp   x8, 190078
    0x1c8c4eee4 <+72>:  add    x1, x8, #0x249            ; =0x249 
    0x1c8c4eee8 <+76>:  mov    x0, x19
    0x1c8c4eeec <+80>:  mov    x2, #0x0
    0x1c8c4eef0 <+84>:  ldp    x29, x30, [sp, #0x10]
    0x1c8c4eef4 <+88>:  ldp    x20, x19, [sp], #0x20
    0x1c8c4eef8 <+92>:  b      0x1c8c4cd60              ; objc_msgSend
    0x1c8c4eefc <+96>:  adrp   x8, 241009
    0x1c8c4ef00 <+100>: ldr    x1, [x8, #0xab0]
    0x1c8c4ef04 <+104>: mov    x0, x19
    0x1c8c4ef08 <+108>: ldp    x29, x30, [sp, #0x10]
    0x1c8c4ef0c <+112>: ldp    x20, x19, [sp], #0x20
    0x1c8c4ef10 <+116>: br     x1

如上的汇编,alloc会调用class_createInstance 来创建对象,可以在该函数ret 处查看x0,就是创建出来要返回的对象。 init在源码中什么都不做如下所示:

id _objc_rootInit(id obj)
{
     // In practice, it will be hard to rely on this function.
     // Many classes do not properly chain -init calls.
     return obj;
 }

alloc 如何开辟和创建空间:

 size_t instanceSize(size_t extraBytes) {
       size_t size = alignedInstanceSize() + extraBytes;
       // CF requires all objects be at least 16 bytes.
       if (size < 16 xss=removed xss=removed>instanceSize(extraBytes);并不是真正对象占用的空间
真正实现在calloc,calloc源码在libmalloc中
size是8字节对齐,但是calloc里,真正跑在64位手机上,是16字节对齐的
  • 在任何一个OC函数都能敲出self和_cmd objc_msgSend(ViewController,@selector(viewDidLoad)); //self就是函数的第一个参数ViewController,_cmd就是第二个参数. objc_msgSend的函数原型:objc_msgSend(id _Nullable self, SEL _Nonnull op, …) //后面的…表示参数可扩展

一个对象,假如有一个int类型的age变量,那么再加上isa指针占的8个字节,就是12个字节。

 5-1.png

收藏
1
sina weixin mail 回到顶部