(接上篇)
五. Aspects hook过程详解
先看看函数调用栈的情况
1 2 3 4 5 6 7 8 9 10 11 12 13 |
- aspect_prepareClassAndHookSelector(self, selector, error); ├── aspect_hookClass(self, error) │ ├──aspect_swizzleClassInPlace │ ├──aspect_swizzleForwardInvocation │ │ └──__ASPECTS_ARE_BEING_CALLED__ │ │ ├──aspect_aliasForSelector │ │ ├──aspect_getContainerForClass │ │ ├──aspect_invoke │ │ └──aspect_remove │ └── aspect_hookedGetClass ├── aspect_isMsgForwardIMP ├──aspect_aliasForSelector(selector) └── aspect_getMsgForwardIMP |
从调用栈可以看出,Aspects hook过程主要分4个阶段,hookClass,ASPECTS_ARE_BEING_CALLED,prepareClassAndHookSelector,remove。
1. hookClass
1 2 3 4 |
NSCParameterAssert(self); Class statedClass = self.class; Class baseClass = object_getClass(self); NSString *className = NSStringFromClass(baseClass); |
statedClass 和 baseClass是有区别的的。
1 2 3 4 5 6 7 8 9 |
Class object_getClass(id obj) { if (obj) return obj->getIsa(); else return Nil; } + (Class)class { return self; } |
statedClass 是获取类对象,baseClass是获取到类的isa。
1 2 3 4 5 6 7 8 9 10 11 |
// Already subclassed if ([className hasSuffix:AspectsSubclassSuffix]) { return baseClass; // We swizzle a class object, not a single object. }else if (class_isMetaClass(baseClass)) { return aspect_swizzleClassInPlace((Class)self); // Probably a KVO'ed class. Swizzle in place. Also swizzle meta classes in place. }else if (statedClass != baseClass) { return aspect_swizzleClassInPlace(baseClass); } |
先判断是用来className是否包含hasSuffix:AspectsSubclassSuffix
1 |
static NSString *const AspectsSubclassSuffix = @"_Aspects_"; |
如果包含了@”_Aspects_”后缀,代表该类已经被hook过了,直接return。
如果不包含@”_Aspects_”后缀,再判断是否是baseClass是否是元类,如果是元类,调用aspect_swizzleClassInPlace。如果也不是元类,再判断statedClass 和 baseClass是否相等,如果不相等,说明为KVO过的对象,因为KVO的对象isa指针会指向一个中间类。对KVO中间类调用aspect_swizzleClassInPlace。
1 2 3 4 5 6 7 8 9 10 11 12 |
static Class aspect_swizzleClassInPlace(Class klass) { 9a6be4a26713df96cd971.png" alt="111194012-362f68c0c95d15f4">
(接上篇) 五. Aspects hook过程详解先看看函数调用栈的情况
从调用栈可以看出,Aspects hook过程主要分4个阶段,hookClass,ASPECTS_ARE_BEING_CALLED,prepareClassAndHookSelector,remove。 1. hookClass
statedClass 和 baseClass是有区别的的。
statedClass 是获取类对象,baseClass是获取到类的isa。
先判断是用来className是否包含hasSuffix:AspectsSubclassSuffix
如果包含了@”_Aspects_”后缀,代表该类已经被hook过了,直接return。
|