iOS 类拓展的加载

116 阅读1分钟

什么是类拓展呢?

类拓展就是一个匿名的分类。

  • 类拓展
@interface LGPerson ()
@property (nonatomic, copy) NSString *ext_name;
@property (nonatomic, copy) NSString *ext_subject;
- (void)extH_method;
@end
  • 分类
@interface NSObject (KC)

@end

类拓展的作用

给当前的类增加属性和方法。

类拓展何时加载到主类

我们继续来到_read_images中来一探究竟。

image.png
我们在_read_images的这个地方做一个小的处理并且打上断点查看ro中是否存在我们需要的数据。

(lldb) p ro
(const class_ro_t *) $0 = 0x0000000100002360
(lldb) p *$0
(const class_ro_t) $1 = {
  flags = 388
  instanceStart = 8
  instanceSize = 40
  reserved = 0
  ivarLayout = 0x0000000100001f82 "\x04"
  name = 0x0000000100001f79 "LGPerson"
  baseMethodList = 0x0000000100002180
  baseProtocols = 0x0000000000000000
  ivars = 0x0000000100002290
  weakIvarLayout = 0x0000000000000000
  baseProperties = 0x0000000100002318
  _swiftMetadataInitializer_NEVER_USE = {}
}
(lldb) p $1.baseMethodList
(method_list_t *const) $2 = 0x0000000100002180
(lldb) p *$2
(method_list_t) $3 = {
  entsize_list_tt<method_t, method_list_t, 3> = {
    entsizeAndFlags = 24
    count = 11
    first = {
      name = "extM_method"
      types = 0x0000000100001f84 "v16@0:8"
      imp = 0x0000000100001a90 (objc-debug`-[LGPerson extM_method] at LGPerson.m:23)
    }
  }
}
(lldb) p $3.get(0)
(method_t) $4 = {
  name = "extM_method"
  types = 0x0000000100001f84 "v16@0:8"
  imp = 0x0000000100001a90 (objc-debug`-[LGPerson extM_method] at LGPerson.m:23)
}
(lldb) p $3.get(1)
(method_t) $5 = {
  name = "extH_method"
  types = 0x0000000100001f84 "v16@0:8"
  imp = 0x0000000100001ac0 (objc-debug`-[LGPerson extH_method] at LGPerson.m:27)
}
(lldb) p $3.get(2)
(method_t) $6 = {
  name = ".cxx_destruct"
  types = 0x0000000100001f84 "v16@0:8"
  imp = 0x0000000100001cb0 (objc-debug`-[LGPerson .cxx_destruct] at LGPerson.m:17)
}
(lldb) p $3.get(3)
(method_t) $7 = {
  name = "name"
  types = 0x0000000100001f8c "@16@0:8"
  imp = 0x0000000100001af0 (objc-debug`-[LGPerson name] at LGPerson.h:13)
}
(lldb) p $3.get(4)
(method_t) $8 = {
  name = "setName:"
  types = 0x0000000100001f94 "v24@0:8@16"
  imp = 0x0000000100001b20 (objc-debug`-[LGPerson setName:] at LGPerson.h:13)
}
(lldb) p $3.get(5)
(method_t) $9 = {
  name = "mName"
  types = 0x0000000100001f8c "@16@0:8"
  imp = 0x0000000100001b60 (objc-debug`-[LGPerson mName] at LGPerson.m:12)
}
(lldb) p $3.get(6)
(method_t) $10 = {
  name = "setMName:"
  types = 0x0000000100001f94 "v24@0:8@16"
  imp = 0x0000000100001b90 (objc-debug`-[LGPerson setMName:] at LGPerson.m:12)
}
(lldb) p $3.get(7)
(method_t) $11 = {
  name = "ext_name"
  types = 0x0000000100001f8c "@16@0:8"
  imp = 0x0000000100001bd0 (objc-debug`-[LGPerson ext_name] at LGPerson+LGExtension.h:14)
}
(lldb) p $3.get(8)
(method_t) $12 = {
  name = "setExt_name:"
  types = 0x0000000100001f94 "v24@0:8@16"
  imp = 0x0000000100001c00 (objc-debug`-[LGPerson setExt_name:] at LGPerson+LGExtension.h:14)
}
(lldb) p $3.get(9)
(method_t) $13 = {
  name = "ext_subject"
  types = 0x0000000100001f8c "@16@0:8"
  imp = 0x0000000100001c40 (objc-debug`-[LGPerson ext_subject] at LGPerson+LGExtension.h:15)
}
(lldb) p $3.get(10)
(method_t) $14 = {
  name = "setExt_subject:"
  types = 0x0000000100001f94 "v24@0:8@16"
  imp = 0x0000000100001c70 (objc-debug`-[LGPerson setExt_subject:] at LGPerson+LGExtension.h:15)
}

通过上面的lldb调试我们可以看到,类拓展在我们的类被加载之前就已经拥有了这些数据。那么据推测就只有一个地方可以实现,那就是编译阶段。

如果我们的类拓展被建立成单独的.h文件并且没有被引用的话,那么这个文件的中的数据是不会被编译进来的。