Runtime 中types 类型编码的意思

故事的发生还要说到一个小功能:让UISearchBar的placeholder文字居左显示,就看到了上的一篇:http://www.jianshu.com/p/86410191b4b2 思路介绍的很好。最核心的东西也就是RunTimeNSInvocation改写系统自带方法。

现在我们倒推我们的思考过程

1,知其然<不知>其所以然

1.我们查找到了一个系统方法,然后替换系统方法,一个分类扩展一个方法就搞定
-(void)changeLeftPlaceholder:(NSString *)placeholder {
    self.placeholder = placeholder;
    SEL centerSelector = NSSelectorFromString([NSString stringWithFormat:@"%@%@", @"setCenter", @"Placeholder:"]);
    if ([self respondsToSelector:centerSelector]) {
        BOOL centeredPlaceholder = NO;
        NSMethodSignature *signature = [[UISearchBar class] instanceMethodSignatureForSelector:centerSelector];
        NSInvocation *invocation = [NSInvocation invocationWithMethodSignature:signature];
        [invocation setTarget:self];
        [invocation setSelector:centerSelector];
        [invocation setArgument:¢eredPlaceholder atIndex:2];
        [invocation invoke];
    }
}
2.我们Runtime打印系统方法查找到了一个设置placeholder居中的一个方法
NSString *name = NSStringFromSelector(selector);
const char *type =  method_getTypeEncoding(method);
NSLog(@"调用方法: %@ Type: %s",name,type);

打印很多,找到一个相关结果:

调用方法: setCenterPlaceholder: Type: v20@0:8B16
3,我们试着去理解这个方法
setCenterPlaceholder:

字面上理解这个方法是设置placeholder文字居中的方法,后面:跟了一个参数。好吧,我们需要知道这个参数的类型,这样才能确定这个方法是否可以被修改。
Runtime中method_getTypeEncoding() 我们可以打印setCenterPlaceholder:的参数类型

/** 
 * Returns a string describing a method's parameter and return types.
 * 
 * @param m The method to inspect.
 * 
 * @return A C string. The string may be \c NULL.
 */
OBJC_EXPORT const char *method_getTypeEncoding(Method m) 
    OBJC_AVAILABLE(10.5, 2.0, 9.0, 1.0);

我们的打印结果是:Type: v20@0:8B16
这都到了今天我要说的重点types类型编码

2,知其然<知>其所以然

types在官方文档上的解释:

An array of characters that describe the types of the arguments to the method. For possible values,Since the function must take at least two arguments—self and _cmd, the second and third characters must be “@:” (the first character is the return type).

可见他是一个characters 字符集合,表示一个方法或属性的字符编码,一般对于OCRuntime中,其至少有两个字符:@:,其中第二个@代表self,方法的调用者,第三个:代表方法的_cmd指针,第一个值是返回类型。

说到这里再来看看我们这个方法setCenterPlaceholder:的类型编码:v20@0:8B16,这里我们先不看数字(下面会讲数字的含义)为v@:B,我们看一下,这第二个字符@,第三个字符:是不是就刚好印证了官方文档上的说的,那么问题来了第一个v代表什么了,答案就在这个表里

Runtime 中types 类型编码的意思_第1张图片
image.png

通过这个表你会发现,v代表void,就是无返回值空类型,那么最后的B就代表C或C++的bool类型了。好了,到这里我们就可以解释一下方法setCenterPlaceholder:的参数类型了:
这个方法传入了一个布尔值,返回结果是void
好了,我们根据字面意思和传入的参数类型判断这个方法可以设置'placeholder'文字是否居中了。

那么那些数字又代表什么?

我们在UISearchBar的分类里面来一个方法:

-(void)printAllSEL{
    unsigned int count;
    Method *methods = class_copyMethodList([self class], &count);
    for (int i = 0; i < count; i++){
        Method method = methods[i];
        SEL selector = method_getName(method);
        NSString *name = NSStringFromSelector(selector);
        const char *type =  method_getTypeEncoding(method);
        NSLog(@"调用方法: %@ Type: %s",name,type);
    }
}

打印结果部分如下:

调用方法: _animatedAppearanceBarButtonItem Type: @16@0:8

调用方法: _setBackgroundLayoutNeedsUpdate: Type: v20@0:8B16

调用方法: _setBackdropStyle: Type: v24@0:8Q16

调用方法: _backdropStyle Type: Q16@0:8

调用方法: setCenterPlaceholder: Type: v20@0:8B16

调用方法: _hasDarkUIAppearance Type: B16@0:8

调用方法: searchFieldLeftViewMode Type: q16@0:8

调用方法: setSearchFieldLeftViewMode: Type: v24@0:8q16

调用方法: _alternateTitle Type: @16@0:8

调用方法: _setCancelButtonWantsLetterpress Type: v16@0:8

总结一下规律,你会发现所有的第二个@后面都是0,第三个:都是8,好的,可能是一些偏移量之类的,文档没介绍,也不知道啥意思?不过可以参考这个小文章,https://code.google.com/archive/p/jscocoa/wikis/MethodEncoding.wiki
欢迎知道的同学留言告知,相互学习,谢谢!

碰到一个问题,我们还是应该多思考,还是孔夫子说的好:学而不思则罔,思而不学则殆

你可能感兴趣的:(Runtime 中types 类型编码的意思)