来自NSMethodSignature的BOOL编码错误 [英] BOOL encoding wrong from NSMethodSignature

查看:56
本文介绍了来自NSMethodSignature的BOOL编码错误的处理方法,对大家解决问题具有一定的参考价值,需要的朋友们下面随着小编来一起学习吧!

问题描述

使用[NSMethodSignature getArgumentTypeAtIndex]函数时,我遇到了非常奇怪的行为.它返回BOOL类型的'@'字符,根据Objective-c

I've encountered really odd behaviour when using [NSMethodSignature getArgumentTypeAtIndex] function. It returns me '@' character for BOOL type which in wrong according to objective-c type encodings. If I use objc\runtime.h library method method_getTypeEncoding BOOL type is correctly represented as a 'B', however I don't understand why it's not working with higher level layer NSMethodSignature. Following code demonstrates the problem:

-(void)viewDidAppear:(BOOL)animated
{
    [super viewDidAppear:animated];

    NSInvocation* inv = [NSInvocation invocationWithMethodSignature:[self methodSignatureForSelector:@selector(viewDidAppear:)]];
    const char* encFromGetArgument = [[inv methodSignature] getArgumentTypeAtIndex:2];

    const char* encFromMethodSignature = method_getTypeEncoding(class_getInstanceMethod([self class], @selector(viewDidAppear:)));;
    const char* methodEncodingPure = [[[[NSString stringWithUTF8String:encFromMethodSignature] componentsSeparatedByCharactersInSet:[NSCharacterSet decimalDigitCharacterSet]] componentsJoinedByString:@""] UTF8String];//remove stack sizes


    NSLog(@"BOOL arg from NSMethodSignature: %s", encFromGetArgument);
    NSLog(@"BOOL arg from objc/runtime.h: %c", methodEncodingPure[3]);//first type is for return, second is target, third is selector
}

上面的内容令人惊讶地(至少对于男性而言)显示以下内容:

The above surprisingly(at least for men) prints the following:

来自NSMethodSignature的BOOL arg:@

BOOL arg from NSMethodSignature: @

来自objc/runtime.h的布尔参数:B

BOOL arg from objc/runtime.h: B

我目前正在使用自己的实现来避免这种奇怪的行为,但是我想知道我是否缺少某些东西,或者仅仅是一个错误.我唯一的线索是BOOL是原始的,并且这样,在调用Objective-C方法时就不能直接使用它.但是,当我尝试对其进行检查时,[object isKingOfClass:[NSNumber class]]返回NO.

I'm currently using my own implementation to avoid this odd behaviour however I want to know if I'm missing something or it's just a bug. My only clue is that BOOL is primitive and like this it cannot be used directly when calling objective-c methods. However when I try to check it [object isKingOfClass:[NSNumber class]] returns NO.

更新

好的,我已经将XCode更新到最新版本(6.1 6A1052d),并且情况大大改善了.但是,我现在的问题是将无符号char编码与真正的bool编码区分开.我知道在旧版本中BOOL是typedef作为char,但是我如何才能完成真正的char vs BOOL编码?我的结果现在是:

Ok I've update XCode to the latest version(6.1 6A1052d) and situation greatly improves. However my problem now is to distinguish unsigned char encoding from real bool encoding. I know in old versions BOOL is typedef as a char, but how I can accomplish real char vs BOOL encoding? My results now are:

对于模拟器iPhone6 和真实设备 iPhone6 ,我收到了:

For Simulator iPhone6 and real device iPhone6 I received:

argument 2: -------- -------- -------- --------
        type encoding (B) 'B'
        flags {}

BOOL arg from NSMethodSignature: B
BOOL arg from objc/runtime.h: B

很棒,但是对于模拟器iPhone4s 和真实设备 iPhone5 ,我会得到:

which is awesome, however for simulator iPhone4s, and real device iPhone5 I'm getting:

argument 2: -------- -------- -------- --------
        type encoding (c) 'c'
        flags {isSigned}

BOOL arg from NSMethodSignature: c
BOOL arg from objc/runtime.h: c

我非常确定,如果我检查iPhone5s,它将获得与iPhone6相同的输出(因为我认为这完全是关于64位体系结构的).因此,我现在的问题是如何正确解决旧设备,如何为它们区分BOOL字符?还是我应该假设如果编码为'c'并且参数等于'1',则为YES,而对于'0',则为NO?

I'm pretty sure that if I check iPhone5s it'll get the same output as iPhone6(as I think it's all about the 64-bit architecture). So my question now is how to properly workaround older devices, how to distinguish char of BOOL for them? Or should I just assume that if encoding is 'c' and argument is equal to '1' we have YES, and for '0' we have NO?

推荐答案

char *buf1 = @encode(BOOL);
NSLog(@"bool type is: %s", buf1);

在32位模拟器上,encode(BOOL)返回'c',而在64位模拟器上,它返回'B'.在构建设置"中,将体系结构"更改为$(ARCHS_STANDARD_32_BIT),然后它将为您返回"c".

On 32bit simulator, encode(BOOL) returns 'c', while on 64 bit, it returns a 'B'. In Build Settings, change Architectures to $(ARCHS_STANDARD_32_BIT), then it will returns 'c' for you.

在objc/objc.h文件中.

in the objc/objc.h file.

#define OBJC_BOOL_DEFINED

/// Type to represent a boolean value.
#if !defined(OBJC_HIDE_64) && TARGET_OS_IPHONE && __LP64__
typedef bool BOOL;
#else
typedef signed char BOOL; 
// BOOL is explicitly signed so @encode(BOOL) == "c" rather than "C" 
// even if -funsigned-char is used.
#endif

32位BOOL是一种带符号的char类型.您可以将其与未签名的字符区分开来.

BOOL in 32bit is a typeof signed char. You can distinguish it from unsigned char.

@encode(char) --> 'c'
@encode(unsigned char) --> 'C'

您可以通过判断设备是32位还是64位. ,如果它是32位,则'c'对BOOL检查有效.

You can tell a device is in 32bit or 64bit from here,and if it is in 32 bit, 'c' is valid for BOOL check.

这篇关于来自NSMethodSignature的BOOL编码错误的文章就介绍到这了,希望我们推荐的答案对大家有所帮助,也希望大家多多支持IT屋!

查看全文
登录 关闭
扫码关注1秒登录
发送“验证码”获取 | 15天全站免登陆