1.Block有3种类型:NSGlobalBlock
, NSMallocBlock
和NSStackBlock
三种,父类为NSBlock
.
NSGlobalBlock
位于全局区,在不捕获外部参数或者全局变量的情况下为此类型.retain
,copy
和release
无效NSMallocBlock
位于堆区,从栈区复制过来的。retain
,release
无效NSStackBlock
位于栈区,引用外部变量时为此类。在ARC下,一般ARC会自动将block从堆区copy到栈区。支持retain
和release
http://ibloodline.com/articles/2016/01/20/memory2-block.html
在ARC下进行打印的话,只会看到
NSGlobalBlock
和NSMallocStack
两种类型的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;
}
((bool (*)(id, SEL))(void *) objc_msgSend)((id)model, meta->_getter)
如果没理解错的话,应该是将objc_msgSend
这个函数强制转换为bool (*) (id, SEL)
类型