YYModel学习笔记

398 阅读4分钟

1.Block有3种类型:NSGlobalBlock, NSMallocBlockNSStackBlock三种,父类为NSBlock.

  • NSGlobalBlock位于全局区,在不捕获外部参数或者全局变量的情况下为此类型. retain, copyrelease无效
  • NSMallocBlock位于堆区,从栈区复制过来的。retain, release无效
  • NSStackBlock位于栈区,引用外部变量时为此类。在ARC下,一般ARC会自动将block从堆区copy到栈区。支持retainrelease

http://ibloodline.com/articles/2016/01/20/memory2-block.html

在ARC下进行打印的话,只会看到NSGlobalBlockNSMallocStack两种类型的block,原因是因为赋值给strong对象时会自动进行copy

int i=0; NSLog(@"%@", ^{ NSLog(@"stack block here, i=%d", i); }); //<NSStackBlock: 0x7fff592eacf8> void (^block)()=^{ NSLog(@"stack block here, i=%d", i); }; NSLog(@"%@",block);

使用__block修饰的变量与全局变量在被block内部使用时,block是根据变量的地址来获取值,而局部变量的话则是copy一次后进行使用:

      int i = 0;
      void (^block1)() = ^{
          NSLog(@"Block i: %p", &i);
          NSLog(@"Block i: %d", i);
      };
      
      static int k = 1;
      void (^block2)() = ^{
          NSLog(@"Block k: %p", &k);
          NSLog(@"Block k: %d", k);
      };
      
      __block int j = 1;
      void (^block3)() = ^{
          NSLog(@"Block j: %p", &j);
          NSLog(@"Block j: %d", j);
      };
      NSLog(@"i: %p", &i);
      i++;
      block1();
      NSLog(@"j: %p", &j);
      j++;
      block3();
      NSLog(@"k: %p", &k);
      k++;
      block2();

输出如下:

2017-06-06 10:39:11.680 LearnYYKit[1694:98529] i: 0x7fff5f9b159c
2017-06-06 10:39:11.681 LearnYYKit[1694:98529] Block i: 0x60000004b960
2017-06-06 10:39:11.682 LearnYYKit[1694:98529] Block i: 0
2017-06-06 10:39:11.682 LearnYYKit[1694:98529] j: 0x60000002cc78
2017-06-06 10:39:11.682 LearnYYKit[1694:98529] Block j: 0x60000002cc78
2017-06-06 10:39:11.682 LearnYYKit[1694:98529] Block j: 2
2017-06-06 10:39:11.683 LearnYYKit[1694:98529] k: 0x100251370
2017-06-06 10:39:11.683 LearnYYKit[1694:98529] Block k: 0x100251370
2017-06-06 10:39:11.683 LearnYYKit[1694:98529] Block k: 2

好像有点跑题,不过刚好看到从获取NSBlock类的方法时顺带复习一下Block的知识。。。。

2.YYEncodingType分成三种类型:

  • 类型: unknown, void, bool...
  • 修饰符: in, out, const...
  • 属性修饰符: readonly, nonatomic, weak, ...

3.YYClassInfo的类:

YYClassIvarInfo YYClassMethodInfo YYClassPropertyInfo YYClassInfo
Ivar ivar Method method objc_property_t property Class cls
NSString *name NSString *name NSString *name Class superCls
ptrdiff_t offset(ptrdiff_t表示的是两个指针之间的差) SEL sel YYEncodingType type Class metaCls
NSString *typeEncoding IMP imp NSString *ivarName BOOL isMeta
NSString *typeEncoding Class cls NSString *name
NSString *returnTypeEncoding NSString *protocols YYClassInfo superClassInfo
NSString *argumentTypeEncodings SEL getter NSDictionary * ivarInfos
SEL setter NSDictionary *methodInfos
NSDictionary *propertyInfos

通过这几个类,我们也能看出在OC中,一个对象在runtime时的结构,实际上YYModel的这几个类就是根据isa指针的指向来构造完成。

4.对于property的编码中,对象的类型的编码是根据@""xxx""来判断,protocol是根据@""""来判断: e.g:

// 利用NSLog输出的话:
@“Student”
@"<MyProtocol>"

5.获取Meta类时,使用object_getClass()这个函数来获取。因为object_getClass()获取的是isa的指向 6.在YYClassInfo中,有一个classInfoWithClass:的初始化的类函数,其中有两个CFMutableDictionaryRef的对象,用于缓存类以及元类的信息。另外,在对这两个对象的读写过程中,使用了GCD的信号量来进行锁操作。

7.dispatch_semaphore_wait()会将信号量减1,当信号量<=0的时候,当前队列会进入等待状态,直到调用dispatch_semaphore_signal()函数将信号量增加到大于0,再继续操作。一般用法:

dispatch_semaphore_t dsema = dispatch_semaphore_create(1);
dispatch_semaphore_wait(dsema);
// 只允许单个线程操作的代码
dispatch_semaphore_signal(dsema);

8.YYValueForKeyPath用于从NSDictionary中取值,可用于多层嵌套的情况 9._YYModelPropertyMeta: 对象中的属性

@interface _YYModelPropertyMeta : NSObject {
  @package
  NSString *_name;             ///< s属性名称
  YYEncodingType _type;        ///< 类型
  YYEncodingNSType _nsType;    ///< 在Foundation中的类型
  BOOL _isCNumber;             ///< 是否为C的基本类型
  Class _cls;                  ///< 所属的类
  Class _genericCls;           ///< container's generic class, or nil if threr's no generic class
  SEL _getter;                 ///< getter方法
  SEL _setter;                 ///< setter方法
  BOOL _isKVCCompatible;       ///< 是否能使用KVC访问
  BOOL _isStructAvailableForKeyedArchiver; ///< 能否进行归档解档
  BOOL _hasCustomClassFromDictionary; ///< 是否实现了+modelCustomClassForDictionary:方法
  
  NSString *_mappedToKey;      ///< 所对应的key
  NSArray *_mappedToKeyPath;   ///< 对应的keyPath
  NSArray *_mappedToKeyArray;  ///< key或者keyPath
  YYClassPropertyInfo *_info;  ///< 属性Info
  _YYModelPropertyMeta *_next; ///< 指向下一个共享同个key的meta对象
}

10.在使用NSKeyedUnarchiver解档的时候,对于结构体来说, 只支持下面几种NSValue的类:CGSize, CGRect, CGPoint, UIOffset, UIEdgeInset, CGAffineTransform 11._YYModelMeta实例:

@interface _YYModelMeta : NSObject {
  @package
  YYClassInfo *_classInfo;
  /// Key:映射的key或者keyPath, Value:_YYModelPropertyMeta.
  NSDictionary *_mapper;
  /// Model所有的property meta
  NSArray *_allPropertyMetas;
  /// 给定keypath的property meta
  NSArray *_keyPathPropertyMetas;
  /// 给定多个keys对应的property meta
  NSArray *_multiKeysPropertyMetas;
  /// _mapper的数量
  NSUInteger _keyMappedCount;
  /// Model的类.
  YYEncodingNSType _nsType;
  
  BOOL _hasCustomWillTransformFromDictionary;
  BOOL _hasCustomTransformFromDictionary;
  BOOL _hasCustomTransformToDictionary;
  BOOL _hasCustomClassFromDictionary;
}
  1. ((bool (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)如果没理解错的话,应该是将objc_msgSend这个函数强制转换为bool (*) (id, SEL)类型