美文网首页
aspects 如何Block获得MethodSignature

aspects 如何Block获得MethodSignature

作者: Crazy2015 | 来源:发表于2019-05-07 18:45 被阅读0次

MethodSignature
一个问题是如何Block获得MethodSignature。Block没有selector,但发现NSMethodSignature有这样一个方法-[NSMethodSignature signatureWithObjCTypes:],那问题转化成如何从Block获得编码的Signature。
自定义Block定义如下:

// Block internals.
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获得MethodSignature

NSInvocation的创建, 需要signature, argument.
signature可以从block中转换过来, 而参数则可以从原来的AspectInfo对象中取出来做转换.

void *desc = layout->descriptor这个指针就是用于获取block的签名了, 根据clang的源码, 签名位于descriptor结构体的第三个变量, 所以将指针移动两个单位.

flag用于判断block的具体类型BLOCK_HAS_COPY_DISPOSE, 代表这个block是否有捕获外部参数, 如果有捕获, 则descriptor中会多插入两个变量, 所以需要将desc指针再移动两个单位

static NSMethodSignature *aspect_blockMethodSignature(id block, NSError **error) {
    AspectBlockRef layout = (__bridge void *)block;
    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);
    return [NSMethodSignature signatureWithObjCTypes:signature];
}

相关资料:
http://clang.llvm.org/docs/Block-ABI-Apple.html(# Block Implementation Specification
)
http://wereadteam.github.io/2016/06/30/Aspects/(面向切面编程之 Aspects 源码解析及应用)
https://juejin.im/post/5a2fd67b5188253e2470f2f8(iOS AOP 框架 - Aspects 源码解读)

相关文章

网友评论

      本文标题:aspects 如何Block获得MethodSignature

      本文链接:https://www.haomeiwen.com/subject/onmyoqtx.html