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 源码解读)
网友评论