1. 程式人生 > >RunTime 運行時

RunTime 運行時

mage clas ins bsp exc logs class chang oid

簡單介紹RunTime 運行時的用法

以下操作都需要導入頭文件

#import <objc/message.h>

#pragma mark -- 發消息


技術分享

//OC方法調用的本質就是讓對象發消息
Person * p = [[Person alloc] init];

//[p eat];//底層是發消息

//對象方法
objc_msgSend(p, @selector(eat));

技術分享技術分享

//類方法

[Person eat];

//類方法
objc_msgSend([Person class], @selector(eat));

#pragma mark -- 交換換方法的實現

目的:當你調用系統方法的時候,為系統自帶的方法增加一些特有的功能!

//1、創建方法所屬的類的分類

//創建URL的分類

+ (void)load

{//當這個類被加載進內存的時候調用這個方法,執行一次
  //交換方法的實現 根據方法標號 找到對應的返回實現,交換實際執行的方法
  Method systemURLWithString = class_getClassMethod([NSURL class], @selector(URLWithString:));

  Method myURLWithString = class_getClassMethod([NSURL class], @selector(my_URLWithString:));

  method_exchangeImplementations(systemURLWithString, myURLWithString);
}

//實現自己的方法

+ (nullable instancetype)my_URLWithString:(NSString *)URLString;
{
  //實際會走系統的URLWithString方法
  NSURL * url = [NSURL my_URLWithString:URLString];
  if (url == nil) {
    NSLog(@"url有問題");//做一些需要特殊處理的操作
    return nil;
  }
  return url;
}

#pragma mark - 動態的增加方法

//一個類調用了一個沒有實現的類方法時,就會調用這個方法

//沒有返回值
void aaa(id self, SEL _cmd, id param) {
  NSLog(@"%@ %@ %@", self, NSStringFromSelector(_cmd), param);
}


//sel:沒有實現的方法

+ (BOOL)resolveClassMethod:(SEL)sel
{
  if (sel == @selector(eat:)) {
  // cls: 給哪一個類添加方法 SEL:方法標號 IMP:方法實現 types:方法類型
  //"v@:" --> v代表void @代表id類型對象 :代表SEL
  class_addMethod(self, sel, (IMP)aaa, "v@:@");
  return YES;
}
return [super resolveClassMethod:sel];
}


//一個類調用了一個沒有實現的對象方法時,就會調用這個方法
+ (BOOL)resolveInstanceMethod:(SEL)sel
{
  return return [super resolveInstanceMethod:sel];
}

#pragma mark - 動態的增加方法

// 1、創建分類

.h中增加屬性

@property (nonatomic, copy) NSString * name;

// 註意:給分類增加屬性會生成setter和getter的方法聲明,不會生成setter和getter的實現,需要自己實現

- (void)setName:(NSString *)name
{
/*
* id object 給哪個對象的屬性賦值
const void *key 屬性對應的key
id value 設置屬性值為value
objc_AssociationPolicy policy 使用的策略
objc_setAssociatedObject(<#id object#>, <#const void *key#>, <#id value#>, <#objc_AssociationPolicy policy#>)
*/
objc_setAssociatedObject(self, @"name", name, OBJC_ASSOCIATION_COPY_NONATOMIC);

}

- (NSString *)name
{
return objc_getAssociatedObject(self, @"name");
}

#pragma mark -- 查找子類方法


+ (NSArray *)findAllSubClassofClass:(Class)superClass
{
  int count = objc_getClassList(NULL, 0);

  NSMutableArray *output = [NSMutableArray array];

  if (count <= 0) {//發生錯誤或者沒有子類

[email protected] @"Couldn‘t retrieve Obj-C class-list";
    return output;
  }

  Class *classes = (__unsafe_unretained Class *)malloc(sizeof(Class) * count);

  count = objc_getClassList(classes, count);

  for (int i = 0; i < count; ++i) {

    if (superClass == class_getSuperclass(classes[i])) {//子類

      [output addObject:classes[i]];
    }
  }
  //釋放C 語言的對象
  free(classes);

  return output;
}

有任何關於iOS開發的問題!歡迎下方留言!!!或者郵件[email protected] 雖然我不一定能夠解答出來,但是我會請教iOS開發高手!!!解答您的問題!!!

RunTime 運行時