Runtime運(yùn)行時(shí)之Class常用方法

原文地址

注: 此篇中記錄的是以class開頭的runtime函數(shù)

一、創(chuàng)建對(duì)象

創(chuàng)建一個(gè)對(duì)象

id class_createInstance(Class cls, size_t extraBytes)
  • cls: 類型

  • extraBytes: 分配的內(nèi)存大小

  • 返回值: cls類型的實(shí)例對(duì)象

例子:

size_t size = class_getInstanceSize([Person class]);
Person *person = class_createInstance([Person class], size);

二、類名、父類、實(shí)例變量、成員變量、屬性、實(shí)例方法、類方法、方法實(shí)現(xiàn)

獲取指定類的類名 (char *類型字符串)

const char *class_getName(Class cls)
  • cls: 類型

  • 返回值: 類名 - char * *類型的字符串

例子:

const char *name = class_getName([Person class])

獲取指定類的父類型 (Class類型)

Class class_getSuperclass(Class cls)
  • cls: 類型

  • 返回值: 父類型 Class類型

例子:

Class class = class_getSuperclass([Person class]);

獲取一個(gè)指定類型的實(shí)例占用內(nèi)存大小 (size_t 類型)

size_t class_getInstanceSize(Class cls)
  • cls: 類型

  • 返回值: cls類型的一個(gè)實(shí)例對(duì)象占用內(nèi)存大小

例子:

size_t size = class_getInstanceSize([Person class]);

獲取一個(gè)類中, 指定名稱的實(shí)例成員變量的信息

Ivar class_getInstanceVariable(Class cls, const char *name)
  • cls: 類型

  • name: 成員變量名(屬性帶 "_")

  • 返回值: 成員變量信息

例子:

Ivar ivar = class_getInstanceVariable([self class], "_person")

獲取屬性的信息, 不用打_

objc_property_t class_getProperty(Class cls, const char *name)
  • cls: 類

  • name: 屬性名

  • 返回值: 屬性信息

例子:

objc_property_t property = class_getProperty([self class], "person");

獲取對(duì)象方法信息 ( "-" 方法)

Method class_getInstanceMethod(Class cls, SEL name)
  • cls: 類

  • name: 方法

  • 返回值: 對(duì)象方法信息 - * ### Method類型

例子:

Method method = class_getInstanceMethod([self class], @selector(methodName));

獲取類方法的信息 ( "+" 方法 )

Method class_getClassMethod(Class cls, SEL name)
  • cls: 類

  • name: 方法

  • 返回值: 對(duì)象方法信息 - ### Method類型

例子:

Method method = class_getInstanceMethod([self class], @selector(methodName));

獲取方法的具體實(shí)現(xiàn) (IMP)

IMP class_getMethodImplementation(Class cls, SEL name)
  • cls: 類

  • name: 方法

  • 返回值: 方法的具體實(shí)現(xiàn) ### IMP類型

例子:

IMP imp = class_getMethodImplementation([self class], @selector(methodName));

獲取方法的具體實(shí)現(xiàn), 返回值類型為struct

IMP class_getMethodImplementation_stret(Class cls, SEL name)
  • cls: 類

  • name: 方法

  • 返回值: 方法的具體實(shí)現(xiàn) ### struct IMP類型

例子:

IMP imp = class_getMethodImplementation_stret([self class], @selector(methodName));

三、成員變量列表、屬性列表、方法列表、協(xié)議列表

獲取成員變量列表

Ivar *class_copyIvarList(Class cls, unsigned int *outCount)
  • cls: 類

  • *outCount: 無(wú)符號(hào)整形變量的指針, 用于獲取成員變量數(shù)量

  • 返回值: 成員變量列表

例子:

  unsigned int count;
  Ivar *ivarList = class_copyIvarList([self class], &count);
  for (int i = 0; i < count; i++) {
      Ivar ivar = ivarList[i];
      // 獲取成員屬性名
      NSString *name = [NSString stringWithUTF8String:ivar_getName(ivar)];
      NSString *type = [NSString stringWithUTF8String:ivar_getTypeEncoding(ivar)];
      NSLog(@"%@%@", type, name);
  }

獲取屬性列表

objc_property_t *class_copyPropertyList(Class cls, unsigned int *outCount)
  • cls: 類型

  • *outCount: 無(wú)符號(hào)整形變量的指針, 用于獲取屬性數(shù)量

  • 返回值: 屬性列表

例子:

  unsigned int count;
  objc_property_t *propertyList = class_copyPropertyList([self class], &count);
  for (int i = 0; i < count; i++) {
      objc_property_t property = propertyList[i];
      // 獲取成員屬性名
      NSString *name = [NSString stringWithUTF8String:property_getName(property)];
      NSString *type = [NSString stringWithUTF8String:property_getAttributes(property)];
      NSLog(@"%@%@", type, name);
  }

獲取方法列表

Method *class_copyMethodList(Class cls, unsigned int *outCount)
  • cls: 類

  • *outCount: 無(wú)符號(hào)整形變量的指針, 用于獲取方法數(shù)量

  • 返回值: 方法列表

例子:

  unsigned int count;
  Method *methodList = class_copyMethodList([self class], &count);
  for (int i = 0; i < count; i++) {
      Method method = methodList[i];
      NSLog(@"%s%s", __func__, sel_getName(method_getName(method)));
  }

獲取協(xié)議列表

Protocol *__unsafe_unretained *class_copyProtocolList(Class cls, unsigned int *outCount)
  • cls: 類

  • *outCount: 無(wú)符號(hào)整形變量的指針, 用于獲取協(xié)議數(shù)量

  • 返回值: 協(xié)議列表

例子:

  unsigned int count;
  Protocol *protocolList = class_copyProtocolList(class,&count);
  for (int i = 0; i < count; i++) {
      Protocol *protocol = protocolList[i];
      NSLog(@"%s%s", __func__, [self protocol_getName:protocol]);
  }

四、add: 成員變量、屬性、方法、協(xié)議

添加成員變量(添加成員變量只能在運(yùn)行時(shí)創(chuàng)建的類,且不能為元類)

BOOL class_addIvar(Class cls, const char *name, size_t size, uint8_t alignment, const char *types)
  • cls: 類

  • name: 成員變量名

  • size: 大小

  • alignment: 對(duì)齊方式

  • types: 參數(shù)類型

  • 返回值: YES: 添加成功 NO: 添加失敗

例子:

  if (class_addIvar([Person class], "country", sizeof(NSString *), 0, "@")) {
    NSLog(@"%sadd ivar success", __func__);
  }else{
    NSLog(@"%sadd ivar fail", __func__);
  }

添加屬性

BOOL class_addProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
  • cls: 類

  • name: 屬性名

  • attributes: 參數(shù)

  • attributeCount: 參數(shù)數(shù)量

  • 返回值: YES: 添加成功 NO: 添加失敗

例子:

  objc_property_attribute_t type = { "T", "@\"NSString\"" };
  objc_property_attribute_t ownership = { "&", "N" }; // C = copy
  objc_property_attribute_t backingivar  = { "V", "" };
  objc_property_attribute_t attrs[] = { type, ownership, backingivar };

  if (class_addProperty([_person class], "country", attrs, 3)) {
      NSLog(@"%sadd Property success", __func__);
  }else{
      NSLog(@"%sadd Property fail", __func__);
  }

添加方法

BOOL class_addMethod(Class cls, SEL name, IMP imp, const char *types)
  • cls: 類型

  • name: 方法

  • imp: 方法實(shí)現(xiàn)

  • types: 類型

  • 返回值: YES: 添加成功 NO: 添加失敗

例子:

  if (class_addMethod([self class], NSSelectorFromString(@"runtimeTestMethod:"), class_getMethodImplementation([self class], NSSelectorFromString(@"runtimeTestMethod:")), "v@:@")) {
      NSLog(@"%sadd method success", __func__);
  }else{
      NSLog(@"%sadd method fail", __func__);
  }

添加協(xié)議

BOOL class_addProtocol(Class cls, Protocol *protocol)
  • cls: 類

  • protocol: 協(xié)議

  • 返回值: YES: 添加成功 NO: 添加失敗

例子:

  if (class_addProtocol([_person class], @protocol(RuntimeBaseProtocol))) {
      NSLog(@"%sadd protocol success", __func__);
  }else{
      NSLog(@"%sadd protocol fail", __func__);
  }

五、replace: 屬性、方法

替換屬性的信息(如果沒(méi)有原屬性會(huì)新建一個(gè)屬性)

void class_replaceProperty(Class cls, const char *name, const objc_property_attribute_t *attributes, unsigned int attributeCount)
  • cls: 類

  • name: 屬性名

  • attributes: 類型

  • attributeCount: 類型數(shù)量

  • 無(wú)返回值

例子:

  objc_property_attribute_t type = { "T", "@\"NSString\"" };
  objc_property_attribute_t ownership = { "C", "" }; // C = copy
  objc_property_attribute_t backingivar  = { "V", "" };
  objc_property_attribute_t attrs[] = { type, ownership, backingivar };

  class_replaceProperty([_person class], "country", attrs, 3);

替代方法的實(shí)現(xiàn)

IMP class_replaceMethod(Class cls, SEL name, IMP imp, const char *types)
  • cls: 類

  • name: 被替代的方法

  • imp: 替代方法

  • types: 類型

  • 返回值: IMP

例子:

  class_replaceMethod([_person class], @selector(method1), class_getMethodImplementation([_person class], @selector(method2)), "v@:");

六、Class 判斷

判斷類是否有實(shí)現(xiàn)指定方法

BOOL class_respondsToSelector(Class cls, SEL sel)
  • cls: 類

  • sel: 方法

  • 返回值: YES: 已經(jīng)實(shí)現(xiàn) NO: 沒(méi)有實(shí)現(xiàn)

例子:

  if (class_respondsToSelector([_person class], @selector(methodName))) {
      NSLog(@"%s %@ exist", __func__, NSStringFromClass(class));
  }else{
      NSLog(@"%s %@ non-exist", __func__, NSStringFromClass(class));
  }

查看類是否為元類

BOOL class_isMetaClass(Class cls)
  • cls: 類

  • 返回值: YES: 是元類 NO: 不是元類

例子:

  if (class_isMetaClass(class)) {
      NSLog(@"%s %@ isMetaClass", __func__, NSStringFromClass(class));
  }else{
      NSLog(@"%s %@ non-isMetaClass", __func__, NSStringFromClass(class));
  }

查看類是否遵循指定協(xié)議

BOOL class_conformsToProtocol(Class cls, Protocol *protocol)
  • cls: 類

  • protocol: 協(xié)議

  • 返回值: YES: 已經(jīng)遵循指定協(xié)議 NO: 沒(méi)有遵循指定協(xié)議

例子:

  if (class_conformsToProtocol([Person class], NSProtocolFromString(@"RuntimeBaseProtocol"))) {
      NSLog(@"%s %@ conformsToProtocol %@", __func__, NSStringFromClass(class), NSStringFromProtocol(protocol));
      return YES;
  }else{
      NSLog(@"%s %@ non-conformsToProtocol %@", __func__, NSStringFromClass(class), NSStringFromProtocol(protocol));
      return NO;
}
最后編輯于
?著作權(quán)歸作者所有,轉(zhuǎn)載或內(nèi)容合作請(qǐng)聯(lián)系作者
【社區(qū)內(nèi)容提示】社區(qū)部分內(nèi)容疑似由AI輔助生成,瀏覽時(shí)請(qǐng)結(jié)合常識(shí)與多方信息審慎甄別。
平臺(tái)聲明:文章內(nèi)容(如有圖片或視頻亦包括在內(nèi))由作者上傳并發(fā)布,文章內(nèi)容僅代表作者本人觀點(diǎn),簡(jiǎn)書系信息發(fā)布平臺(tái),僅提供信息存儲(chǔ)服務(wù)。

相關(guān)閱讀更多精彩內(nèi)容

友情鏈接更多精彩內(nèi)容