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)
型別