Aspects源码解读

当我们有需要在所有的控制器的 viewDidLoad 的方法中执行一些代码时,我们可能考虑到在基类控制器 viewDidLoad 方法中添加一些代码。这里就寄希望于所有的开发者都没有忘了继承基类。或者当我们想在指定的某个实例对象的某个方法A中插入一些代码,我们可能考虑到直接进入到这个类,根据某些条件在A方法中添加代码。这其实就对原有类造成一定的破坏。基于这类需求,Aspects 的出现较为完美的解决了这些痛点。

@interface NSObject (Aspects)

+ (id)aspect_hookSelector:(SEL)selector
                           withOptions:(AspectOptions)options
                            usingBlock:(id)block
                                 error:(NSError **)error;

- (id)aspect_hookSelector:(SEL)selector
                           withOptions:(AspectOptions)options
                            usingBlock:(id)block
                                 error:(NSError **)error;

@end

提供两个接口,其中类方法针对一个类所有的实例,实例方法只会针对单个指定对象。

  • selector : 你想hook的方法,这里以 viewDidLoad为例
  • options : 你可以选择在 viewDidLoad 执行前或者之后执行你添加的代码,或者干脆替代掉原有实现
  • block : 你的代码,以block的形式执行
  • error : hook过程可能的错误信息

流程实现

这里以hook UIViewControllerviewDidLoad 方法为例,疏通一下整个实现流程

   [UIViewController aspect_hookSelector:@selector(viewDidLoad)
                             withOptions:AspectPositionAfter
                              usingBlock:^(idinfo) {
                                  NSLog(@"[%@ viewDidLoad]", NSStringFromClass([info.instance class]));
                              } error:nil];

经过一层跳转来到一个C方法

// self : UIViewController 类对象
// selector : viewDidLoad 对应的selector
// options : AspectPositionAfter
// block : block
// error : nil
static id aspect_add(id self, SEL selector, AspectOptions options, id block, NSError **error) {
   NSCParameterAssert(self);
   NSCParameterAssert(selector);
   NSCParameterAssert(block);

   __block AspectIdentifier *identifier = nil;
   aspect_performLocked(^{
       // A: 先检测能否被hook,规则是
       
       // 1. 某些方法不能被hook [@"retain", @"release", @"autorelease", @"forwardInvocation:"]
       // 2. 如果 hook 的是 dealloc 方法,那么 block 必须在 dealloc 执行之前执行。
       // 3. 一个类的继承体系中,一个方法只能被hook一次
       if (aspect_isSelectorAllowedAndTrack(self, selector, options, error)) {
           
           // B: 可以被 hook 的话,则生成一个 AspectIdentifier 并添加到 AspectsContainer 中,
           // AspectsContainer 是由关联对象技术存储在 UIViewController 类对象中。
           AspectsContainer *aspectContainer = aspect_getContainerForObject(self, selector);
           identifier = [AspectIdentifier identifierWithSelector:selector object:self options:options block:block error:error];
           if (identifier) {
               [aspectContainer addAspect:identifier withOptions:options];

               // C: 具体执行 hook 的方法
               aspect_prepareClassAndHookSelector(self, selector, error);
           }
       }
   });
   return identifier;
}

static void aspect_performLocked(dispatch_block_t block) {
   static OSSpinLock aspect_lock = OS_SPINLOCK_INIT;
   OSSpinLockLock(&aspect_lock);
   block();
   OSSpinLockUnlock(&aspect_lock);
}

  • 添加一个aspect的代码在锁的保护下执行 static void aspect_performLocked(dispatch_block_t block)
  • A: 先检测这个类的指定方法能否被 hook
  • B: 检测通过则生成一个 AspectIdentifier 对象用于记录这次hook的信息
  • C: 最后执行 hook 的代码

A: 先检测这个类的指定方法能否被 hook

检测这个方法是否适合被 hook ,如果能被 hood 且被 hook 的是一个类的话,则跟踪这个类整个继承体系。

所谓跟踪整个继承体系是因为:一旦 hook 一个类,会生成一个 AspectTracker0,以 class 为key,AspectTracker0 为value存在静态字典中。
同时,会获取这个类的父类,同样生成一个 AspectTracker1,以 superClass 为key,AspectTracker1 为value存在静态字典中。
并且 将 AspectTracker0 记录在 AspectTracker1 中。再获取父类的父类直到 NSObject.
跟踪的目的在于一个类的继承体系中,一个方法只能被hook一次, 讨论说可能导致死循环

static BOOL aspect_isSelectorAllowedAndTrack(NSObject *self, SEL selector, AspectOptions options, NSError **error) {
    static NSSet *disallowedSelectorList;
    static dispatch_once_t pred;
    dispatch_once(&pred, ^{
        disallowedSelectorList = [NSSet setWithObjects:@"retain", @"release", @"autorelease", @"forwardInvocation:", nil];
    });

    /// 黑名单中的方法不可以被hook
    NSString *selectorName = NSStringFromSelector(selector);
    if ([disallowedSelectorList containsObject:selectorName]) {
        NSString *errorDescription = [NSString stringWithFormat:@"Selector %@ is blacklisted.", selectorName];
        AspectError(AspectErrorSelectorBlacklisted, errorDescription);
        return NO;
    }

    /// 如果 hook 的是 dealloc 方法,那么block的执行时机必须在 dealloc 执行前,
    /// 试想如果在 dealloc执行后,对象都被释放了,再执行block可能会崩溃
    AspectOptions position = options&AspectPositionFilter;
    if ([selectorName isEqualToString:@"dealloc"] && position != AspectPositionBefore) {
        NSString *errorDesc = @"AspectPositionBefore is the only valid position when hooking dealloc.";
        AspectError(AspectErrorSelectorDeallocPosition, errorDesc);
        return NO;
    }

    /// 确保被hook的对象能够响应hook的方法
    if (![self respondsToSelector:selector] && ![self.class instancesRespondToSelector:selector]) {
        NSString *errorDesc = [NSString stringWithFormat:@"Unable to find selector -[%@ %@].", NSStringFromClass(self.class), selectorName];
        AspectError(AspectErrorDoesNotRespondToSelector, errorDesc);
        return NO;
    }

    /// 如果是类的话一个类的继承体系中,一个方法只能被hook一次
    if (class_isMetaClass(object_getClass(self))) {
        Class klass = [self class];
        /// 静态字典 @ {Class : AspectTracker}
        NSMutableDictionary *swizzledClassesDict = aspect_getSwizzledClassesDict();
        Class currentClass = [self class];

        AspectTracker *tracker = swizzledClassesDict[currentClass];
        
        // 如果当前类的子类已经 hook 了这个方法,则不能重复 hook
        if ([tracker subclassHasHookedSelectorName:selectorName]) {
            NSSet *subclassTracker = [tracker subclassTrackersHookingSelectorName:selectorName];
            NSSet *subclassNames = [subclassTracker valueForKey:@"trackedClassName"];
            NSString *errorDescription = [NSString stringWithFormat:@"Error: %@ already hooked subclasses: %@. A method can only be hooked once per class hierarchy.", selectorName, subclassNames];
            AspectError(AspectErrorSelectorAlreadyHookedInClassHierarchy, errorDescription);
            return NO;
        }

        do {
            // 如果当前类的父类已经 hook 了这个方法,则不能重复 hook
            tracker = swizzledClassesDict[currentClass];
            if ([tracker.selectorNames containsObject:selectorName]) {
                if (klass == currentClass) {
                    // Already modified and topmost!
                    return YES;
                }
                NSString *errorDescription = [NSString stringWithFormat:@"Error: %@ already hooked in %@. A method can only be hooked once per class hierarchy.", selectorName, NSStringFromClass(currentClass)];
                AspectError(AspectErrorSelectorAlreadyHookedInClassHierarchy, errorDescription);
                return NO;
            }
        } while ((currentClass = class_getSuperclass(currentClass)));

       
        /// 比如hook MyViewController(继承自UIViewController)的 `viewDidLoad` 方法,那么首先会生成一个 AspectTracker0 记录被hook的方法名(viewDidLoad)和类(MyViewController),将这个 AspectTracker_My 存在静态的字典中。
        /// 然后取到 MyViewController 的父类 UIViewController, 生成一个 AspectTracker1,将 AspectTracker0 存入 AspectTracker1的容器中,以记录 UIViewController的子类被hook的情况
        /// 再取到 UIViewController 的父类 。。。同样操作,直至NSObject。
        currentClass = klass;
        AspectTracker *subclassTracker = nil;
        do {
            tracker = swizzledClassesDict[currentClass];
            if (!tracker) {
                tracker = [[AspectTracker alloc] initWithTrackedClass:currentClass];
                swizzledClassesDict[(id)currentClass] = tracker;
            }
            if (subclassTracker) {
                [tracker addSubclassTracker:subclassTracker hookingSelectorName:selectorName];
            } else { // 针对的是当前类进行hook,所以方法被添加到当前类的被hook方法列表中
                [tracker.selectorNames addObject:selectorName];
            }

            // All superclasses get marked as having a subclass that is modified.
            subclassTracker = tracker;
        }while ((currentClass = class_getSuperclass(currentClass)));
    } else {
        return YES;
    }

    return YES;
}

B: 检测通过则生成一个 AspectIdentifier 对象用于记录这次hook的信息

通过传进来的参数生成一个 AspectIdentifier 对象,并插入到 AspectsContainer 中, AspectsContainer是根据方法名动态绑定到类或者对象上的


+ (instancetype)identifierWithSelector:(SEL)selector
                                object:(id)object
                               options:(AspectOptions)options
                                 block:(id)block
                                 error:(NSError **)error {
    NSCParameterAssert(block);
    NSCParameterAssert(selector);
    NSMethodSignature *blockSignature = aspect_blockMethodSignature(block, error);
    // check signature compatibility, etc.
    if (!aspect_isCompatibleBlockSignature(blockSignature, object, selector, error)) {
        return nil;
    }

    AspectIdentifier *identifier = nil;
    if (blockSignature) {
        identifier = [AspectIdentifier new];
        identifier.selector = selector;
        identifier.block = block;
        identifier.blockSignature = blockSignature;
        identifier.options = options;
        identifier.object = object; // weak
    }
    return identifier;
}


/// 关联对象技术将一个 AspectsContainer 绑定在一个类对象或者实例对象上
/// AspectsContainer 可以包含了一个方法的任一 |前|后|替换| 的AspectIdentifier
/// 取了别名 viewDidLoad -> aspects__viewDidLoad
static AspectsContainer *aspect_getContainerForObject(NSObject *self, SEL selector) {
    NSCParameterAssert(self);
    SEL aliasSelector = aspect_aliasForSelector(selector);
    AspectsContainer *aspectContainer = objc_getAssociatedObject(self, aliasSelector);
    if (!aspectContainer) {
        aspectContainer = [AspectsContainer new];
        objc_setAssociatedObject(self, aliasSelector, aspectContainer, OBJC_ASSOCIATION_RETAIN);
    }
    return aspectContainer;
}

AspectIdentifier

这个类记录了hook时传进来的参数,并最终以 NSInvocation 的方式执行block

@interface AspectIdentifier : NSObject

/// 被hook的方法
@property (nonatomic, assign) SEL selector;

/// 传进来的block
@property (nonatomic, strong) id block;

/// block的方法签名
@property (nonatomic, strong) NSMethodSignature *blockSignature;

/// 被hook的对象(类或者实例)
@property (nonatomic, weak) id object;

/// block的执行时机
@property (nonatomic, assign) AspectOptions options;

@end

AspectsContainer

一个容器类,存储了一个类或者对象的所有 hook 的信息,一个 hook 信息用 AspectIdentifier 表示

@interface AspectsContainer : NSObject

/// 添加一个 AspectIdentifier, 根据 options 存入相应的容器
- (void)addAspect:(AspectIdentifier *)aspect withOptions:(AspectOptions)injectPosition;

/// 移除一个 AspectIdentifier,根据 options 从相应的容器内移除
- (BOOL)removeAspect:(id)aspect;

/// 是否有hood信息
- (BOOL)hasAspects;

/// 在原方法之前执行block的hooks
@property (atomic, copy) NSArray *beforeAspects;

/// 代替原方法执行block的hooks
@property (atomic, copy) NSArray *insteadAspects;

/// 在原方法之后执行block的hooks
@property (atomic, copy) NSArray *afterAspects;

@end

C: 最后执行 hook 的代码

  1. 将一个类的 forwardInvocation: 的实现 替换为 __ASPECTS_ARE_BEING_CALLED__
  2. 生成一个新的方法 aspects__viewDidLoad 保存原有方法 viewDidLoad 的实现
  3. 将指定方法 viewDidLoad 的实现修改为 _objc_msgForward

于是viewDidLoad -> _objc_msgForward 这样调用 viewDidLoad 就会直接执行 _objc_msgForward, 从而触发消息转发执行 forwardInvocation:,而 forwardInvocation:-> __ASPECTS_ARE_BEING_CALLED__。 所以最终调用 viewDidLoad 会执行 __ASPECTS_ARE_BEING_CALLED__.

static void aspect_prepareClassAndHookSelector(NSObject *self, SEL selector, NSError **error) {
    NSCParameterAssert(selector);
    // 1.将一个类的 `forwardInvocation:` 的实现 替换为 `__ASPECTS_ARE_BEING_CALLED__
    Class klass = aspect_hookClass(self, error);
    Method targetMethod = class_getInstanceMethod(klass, selector);
    IMP targetMethodIMP = method_getImplementation(targetMethod);
    if (!aspect_isMsgForwardIMP(targetMethodIMP)) {
        // Make a method alias for the existing method implementation, it not already copied.
        
        const char *typeEncoding = method_getTypeEncoding(targetMethod);
        SEL aliasSelector = aspect_aliasForSelector(selector);
        // 2. 生成一个新的方法 `aspects__viewDidLoad` 保存原有方法 `viewDidLoad` 的实现
        if (![klass instancesRespondToSelector:aliasSelector]) {
            __unused BOOL addedAlias = class_addMethod(klass, aliasSelector, method_getImplementation(targetMethod), typeEncoding);
            NSCAssert(addedAlias, @"Original implementation for %@ is already copied to %@ on %@", NSStringFromSelector(selector), NSStringFromSelector(aliasSelector), klass);
        }

        // We use forwardInvocation to hook in.
        /// 3. 将指定方法 `viewDidLoad` 的实现修改为 `_objc_msgForward`
        class_replaceMethod(klass, selector, aspect_getMsgForwardIMP(self, selector), typeEncoding);
        AspectLog(@"Aspects: Installed hook for -[%@ %@].", klass, NSStringFromSelector(selector));
    }
}
/// 替换掉类方法的 `forwardInvocation:` 的方法实现,将它的实现更改为 `__ASPECTS_ARE_BEING_CALLED__`这个c方法,并确保一个类只会执行一次
/// 如果是实例对象的话,生成一个子类,并修改当前对象的isa指向子类。
static Class aspect_hookClass(NSObject *self, NSError **error) {
    NSCParameterAssert(self);
    Class statedClass = self.class;
    Class baseClass = object_getClass(self);
    NSString *className = NSStringFromClass(baseClass);

    // Already subclassed
    // 已经替换过了
    if ([className hasSuffix:AspectsSubclassSuffix]) {
        return baseClass;

        // We swizzle a class object, not a single object.
        // 替换掉类的 forwardInvocation:方法实现
    }else if (class_isMetaClass(baseClass)) {
        return aspect_swizzleClassInPlace((Class)self);
        // Probably a KVO'ed class. Swizzle in place. Also swizzle meta classes in place.
        /// KVOed类,通过 self.class方法获得的class为原类,而通过object_getClass(self),是KVO后被修改isa指向的真实的class
    }else if (statedClass != baseClass) {
        return aspect_swizzleClassInPlace(baseClass);
    }

    // Default case. Create dynamic subclass.
    const char *subclassName = [className stringByAppendingString:AspectsSubclassSuffix].UTF8String;
    Class subclass = objc_getClass(subclassName);

    if (subclass == nil) {
        subclass = objc_allocateClassPair(baseClass, subclassName, 0);
        if (subclass == nil) {
            NSString *errrorDesc = [NSString stringWithFormat:@"objc_allocateClassPair failed to allocate class %s.", subclassName];
            AspectError(AspectErrorFailedToAllocateClassPair, errrorDesc);
            return nil;
        }

        /// 将一个类的 `forwardInvocation:`方法实现替换为 __ASPECTS_ARE_BEING_CALLED__,如果这个类本身实现了 forwardInvocation:,则生成一个新方法 __aspects_forwardInvocation 保存原有实现
        aspect_swizzleForwardInvocation(subclass);
        
        /// 修改一个类的 class 方法实现,作用是修改了一个类的class使之指向子类,但是使用者通过 [self class] 方法仍然返回原来的类
        aspect_hookedGetClass(subclass, statedClass);
        aspect_hookedGetClass(object_getClass(subclass), statedClass);
        objc_registerClassPair(subclass);
    }

    object_setClass(self, subclass);
    return subclass;
}

/// 替换掉类方法的 `forwardInvocation:` 的方法实现,将它的实现更改为 `__ASPECTS_ARE_BEING_CALLED__`这个c方法,并确保一个类只会执行一次
static Class aspect_swizzleClassInPlace(Class klass) {
    NSCParameterAssert(klass);
    NSString *className = NSStringFromClass(klass);

    _aspect_modifySwizzledClasses(^(NSMutableSet *swizzledClasses) {
        if (![swizzledClasses containsObject:className]) {
            aspect_swizzleForwardInvocation(klass);
            [swizzledClasses addObject:className];
        }
    });
    return klass;
}
/// 修改一个类的 class 方法实现,作用是修改了一个类的class使之指向子类,但是使用者通过 [self class] 方法仍然返回原来的类
static void aspect_hookedGetClass(Class class, Class statedClass) {
    NSCParameterAssert(class);
    NSCParameterAssert(statedClass);
    Method method = class_getInstanceMethod(class, @selector(class));
    IMP newIMP = imp_implementationWithBlock(^(id self) {
        return statedClass;
    });
    class_replaceMethod(class, @selector(class), newIMP, method_getTypeEncoding(method));
}

__ASPECTS_ARE_BEING_CALLED__

我们已经知道,当一个类或者对象调用原有方法时,会来到这个C方法。在这个C方法里面会执行block,根据 options 在block前后执行原来的方法。

// This is the swizzled forwardInvocation: method.
/// 一个类被替换的forwardInvocation:的实现。
/// invocation 触发消息转发时生成的 invocation 对象 invocation.selector = @selector(viewDidLoad)
/// 调用 block
/// 回调原有方法
static void __ASPECTS_ARE_BEING_CALLED__(__unsafe_unretained NSObject *self, SEL selector, NSInvocation *invocation) {
    NSCParameterAssert(self);
    NSCParameterAssert(invocation);
    SEL originalSelector = invocation.selector;
    SEL aliasSelector = aspect_aliasForSelector(invocation.selector);
    // 因为 viewDidLoad 的实现由  aspects__viewDidLoad 保存了,所以这里为了调用原来的实现,需要修改
    invocation.selector = aliasSelector;
    AspectsContainer *objectContainer = objc_getAssociatedObject(self, aliasSelector);
    AspectsContainer *classContainer = aspect_getContainerForClass(object_getClass(self), aliasSelector);
    AspectInfo *info = [[AspectInfo alloc] initWithInstance:self invocation:invocation];
    NSArray *aspectsToRemove = nil;

    // Before hooks.
    aspect_invoke(classContainer.beforeAspects, info);
    aspect_invoke(objectContainer.beforeAspects, info);

    // Instead hooks.
    BOOL respondsToAlias = YES;
    if (objectContainer.insteadAspects.count || classContainer.insteadAspects.count) {
        aspect_invoke(classContainer.insteadAspects, info);
        aspect_invoke(objectContainer.insteadAspects, info);
    }else {
        Class klass = object_getClass(invocation.target);
        do {
            if ((respondsToAlias = [klass instancesRespondToSelector:aliasSelector])) {
                [invocation invoke];
                break;
            }
        }while (!respondsToAlias && (klass = class_getSuperclass(klass)));
    }

    // After hooks.
    aspect_invoke(classContainer.afterAspects, info);
    aspect_invoke(objectContainer.afterAspects, info);

    // If no hooks are installed, call original implementation (usually to throw an exception)
    if (!respondsToAlias) {
        invocation.selector = originalSelector;
        SEL originalForwardInvocationSEL = NSSelectorFromString(AspectsForwardInvocationSelectorName);
        if ([self respondsToSelector:originalForwardInvocationSEL]) {
            ((void( *)(id, SEL, NSInvocation *))objc_msgSend)(self, originalForwardInvocationSEL, invocation);
        }else {
            [self doesNotRecognizeSelector:invocation.selector];
        }
    }

    // Remove any hooks that are queued for deregistration.
    [aspectsToRemove makeObjectsPerformSelector:@selector(remove)];
}

执行block

block的本质是结构体

  • __unused Class isa; : 类型
  • AspectBlockFlags flags:标志位
  • reserved :保留字段
  • invoke: 执行函数
  • descriptor 描述信息

你可以对一个block进行强转后获取执行函数 invoke的签名信息,

typedef NS_OPTIONS(int, AspectBlockFlags) {
    AspectBlockFlagsHasCopyDisposeHelpers = (1 << 25),
    AspectBlockFlagsHasSignature          = (1 << 30)
};
typedef struct _AspectBlock {
    __unused Class isa;
    AspectBlockFlags flags;
    __unused int reserved;
    void (__unused *invoke)(struct _AspectBlock *block, ...);
    struct {
        unsigned long int reserved;
        unsigned long int size;
        // requires AspectBlockFlagsHasCopyDisposeHelpers
        void (*copy)(void *dst, const void *src);
        void (*dispose)(const void *);
        // requires AspectBlockFlagsHasSignature
        const char *signature;
        const char *layout;
    } *descriptor;
    // imported variables
} *AspectBlockRef;

获取block的中的方法签名信息

  • block 中必然有一个方法可以执行,在flags中有体现
  • 通过地址偏移找到这个方法的签名信息
  • 生成 NSMethodSignature 签名对象
  • 通过 NSMethodSignature 生成 NSInvocation
static NSMethodSignature *aspect_blockMethodSignature(id block, NSError **error) {
    AspectBlockRef layout = (__bridge void *)block;
    
    // block 中必然有一个方法可以执行,在flags中有体现
    if (!(layout->flags & AspectBlockFlagsHasSignature)) {
        NSString *description = [NSString stringWithFormat:@"The block %@ doesn't contain a type signature.", block];
        AspectError(AspectErrorMissingBlockSignature, description);
        return nil;
    }
    
    // 通过地址偏移找到这个方法的签名信息
    void *desc = layout->descriptor;
    desc += 2 * sizeof(unsigned long int);
    if (layout->flags & AspectBlockFlagsHasCopyDisposeHelpers) {
        desc += 2 * sizeof(void *);
    }
    if (!desc) {
        NSString *description = [NSString stringWithFormat:@"The block %@ doesn't has a type signature.", block];
        AspectError(AspectErrorMissingBlockSignature, description);
        return nil;
    }
    const char *signature = (*(const char **)desc);
    // 生成 NSMethodSignature 签名对象
    return [NSMethodSignature signatureWithObjCTypes:signature];
}
#define aspect_invoke(aspects, info) \
for (AspectIdentifier *aspect in aspects) {\
    [aspect invokeWithInfo:info];\
    if (aspect.options & AspectOptionAutomaticRemoval) { \
        aspectsToRemove = [aspectsToRemove?:@[] arrayByAddingObject:aspect]; \
    } \
}

static void __ASPECTS_ARE_BEING_CALLED__(__unsafe_unretained NSObject *self, SEL selector, NSInvocation *invocation) {
    ....
    AspectInfo *info = [[AspectInfo alloc] initWithInstance:self invocation:invocation];
    aspect_invoke(..., info)
    .....    
}

将block以 NSInvocation 的形式执行

- (BOOL)invokeWithInfo:(id)info {
    NSInvocation *blockInvocation = [NSInvocation invocationWithMethodSignature:self.blockSignature];
    NSInvocation *originalInvocation = info.originalInvocation;
    NSUInteger numberOfArguments = self.blockSignature.numberOfArguments;

    // Be extra paranoid. We already check that on hook registration.
    if (numberOfArguments > originalInvocation.methodSignature.numberOfArguments) {
        AspectLogError(@"Block has too many arguments. Not calling %@", info);
        return NO;
    }

    // block 如果有参数,则第一个参数为 UIViewController 的实例,第二个参数,为 info,剩下的参数会根据原有方法的参数进行填充
    if (numberOfArguments > 1) {
        [blockInvocation setArgument:&info atIndex:1];
    }
    
    void *argBuf = NULL;
    for (NSUInteger idx = 2; idx < numberOfArguments; idx++) {
        const char *type = [originalInvocation.methodSignature getArgumentTypeAtIndex:idx];
        NSUInteger argSize;
        NSGetSizeAndAlignment(type, &argSize, NULL);
        
        if (!(argBuf = reallocf(argBuf, argSize))) {
            AspectLogError(@"Failed to allocate memory for block invocation.");
            return NO;
        }
        
        [originalInvocation getArgument:argBuf atIndex:idx];
        [blockInvocation setArgument:argBuf atIndex:idx];
    }
    // block 如果有参数,这里将第一个参数修改为 self.block。
    [blockInvocation invokeWithTarget:self.block];
    
    if (argBuf != NULL) {
        free(argBuf);
    }
    return YES;
}

你可能感兴趣的:(Aspects源码解读)