YYModel源码心得

心得一.使用 objc_msgSend 强制转换类型(以下两种方式):

    1.NSString *(*fn)(id, SEL, NSString *) = (NSString *(*)(id, SEL, NSString *))objc_msgSend;

      fn(self, @selector(method1:), @"呵呵");

    2.((uint16_t (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter);
      ((void (*)(id, SEL, id))(void *) objc_msgSend)((id)model, meta->_setter, value);

    // - 调用 IMP 方法
    IMP result7 = class_getMethodImplementation([ViewController class], @selector(method0:));

    int (*px)(id, SEL, NSString *) = (int (*)(id, SEL, NSString *))result7;

  // - 下边的两种写法都可以
    1. px(nil, nil, @"ssss");      2. px(self, @selector(method0:), @"ssss");

    // - 设置一个a类型的对象为 b类型的对象 这是后如果 a,b同时有 eat 方法 [a eat]会调用 b 类中 的 eat 方法
    object_setClass(id a, Class [b class]);

    // - method_setImplementation 和 method_getImplementation 用于交换法方法的实现 这时候调用 [a eat] 实际上会调用 [b eat]的方法的实现(用于方法交换超级好用, 比MethodSwizzle 牛逼多了)
    Method mMethod = class_getInstanceMethod([a class], @selector(eat));
    Method impMethod = class_getInstanceMethod([b class], @selector(eat));
    IMP imp = method_getImplementation(impMethod)
    method_setImplementation(mMethod, imp);



    // - OC 数据类型和 void* 互转 
      Person *person = [[Person alloc]init];
      void *vp = (__bridge void*)person;
      __unsafe_unretained Person *person = (__bridge Person *)vp;

    // - 用 runtime 和 KVC 修改 基本数据类型的值
    int age = 30;

    // - 使用 KVC 修改基本数据类型的值
    [person setValue:@(100) forKey:@"age"];
    
    // - 使用 runtime 修改基本数据类型的值
    int age = 10;
    Ivar i = class_getInstanceVariable([person class], "_age");

    // - 下边两个效果是一样的  只是上边的有警告, 所以使用下边的方法
    object_setIvar(person, i, (__bridge id)(void *)age);
    object_setIvar(person, i, (__bridge id)(*((void **)&age)));

    // -  C语言修改
    /**1. 使用 ivar_getOffset 获取非指针类型的数据 */
    ptrdiff_t ageOffset = ivar_getOffset(class_getInstanceVariable(person.class, "_age"));
    int *ageP = (int *)(person + ageOffset);
    *ageP = 10;
    
    /** 使用2. ivar_getOffset 修改指针类型的数据 */
    ptrdiff_t nameOffset = ivar_getOffset(class_getInstanceVariable(person.class, "_name"));
    void **namePP = (void **)(vp + nameOffset);
    *namePP = @"WXC";

    /** 使用3. ivar_getOffset 获取指针类型的数据 */
    ptrdiff_t sonOffset = ivar_getOffset(class_getInstanceVariable(person.class, "_son"));
    void **sonPP = (void **)(person + sonOffset);
    *sonPP = (__bridge_retained void *)son;

心得二.字符串扫描器:

// - type = @"@\"NSString\"";
@property (nonatomic, copy, readonly) NSString *name; 

// - type = @"@\"<UIKeyInput><UIPickerViewDelegate><UITextSelecting>\"";
@property (nonatomic, strong) id <UIKeyInput, UIPickerViewDelegate, UITextSelecting> testAnyProp;

// - type = @"@\"NSString<UITabBarDelegate><UINavigationBarDelegate>\"";
@property (nonatomic, strong) NSString <UITabBarDelegate, UINavigationBarDelegate> *testAny1Prop;


  if ((type & YYEncodingTypeMask) == YYEncodingTypeObject && _typeEncoding.length) {
      NSScanner *scanner = [NSScanner scannerWithString:_typeEncoding];
      if (![scanner scanString:@"@\"" intoString:NULL]) continue;
      
      NSString *clsName = nil;
      if ([scanner scanUpToCharactersFromSet: [NSCharacterSet characterSetWithCharactersInString:@"\"<"] intoString:&clsName]) {
          if (clsName.length) _cls = objc_getClass(clsName.UTF8String);
      }
      
      NSMutableArray *protocols = nil;
      while ([scanner scanString:@"<" intoString:NULL]) {
          NSString* protocol = nil;
          if ([scanner scanUpToString:@">" intoString: &protocol]) {
              if (protocol.length) {
                  if (!protocols) protocols = [NSMutableArray new];
                  [protocols addObject:protocol];
              }
          }
          [scanner scanString:@">" intoString:NULL];
      }
      _protocols = protocols;
  }

心得三: 信号量的使用

static dispatch_semaphore_t lock;
    dispatch_once(&onceToken, ^{
        lock = dispatch_semaphore_create(1);
    });
    dispatch_semaphore_wait(lock, DISPATCH_TIME_FOREVER);
     // - do someting ...
    dispatch_semaphore_signal(lock);

 

评论
添加红包

请填写红包祝福语或标题

红包个数最小为10个

红包金额最低5元

当前余额3.43前往充值 >
需支付:10.00
成就一亿技术人!
领取后你会自动成为博主和红包主的粉丝 规则
hope_wisdom
发出的红包
实付
使用余额支付
点击重新获取
扫码支付
钱包余额 0

抵扣说明:

1.余额是钱包充值的虚拟货币,按照1:1的比例进行支付金额的抵扣。
2.余额无法直接购买下载,可以购买VIP、付费专栏及课程。

余额充值