Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/116.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios NSMethodSignature中的布尔编码错误_Ios_Objective C_Ios7_Ios8 - Fatal编程技术网

Ios NSMethodSignature中的布尔编码错误

Ios NSMethodSignature中的布尔编码错误,ios,objective-c,ios7,ios8,Ios,Objective C,Ios7,Ios8,我在使用[NSMethodSignature getArgumentTypeAtIndex]函数时遇到了非常奇怪的行为。它返回布尔类型的“@”字符,根据objective-c,该字符是错误的。如果我使用objc\runtime.h库方法,那么getTypeEncoding BOOL类型正确地表示为“B”,但是我不明白为什么它不能与更高级别的层NSMethodSignature一起工作。以下代码演示了该问题: -(void)viewDidAppear:(BOOL)animated { [s

我在使用[NSMethodSignature getArgumentTypeAtIndex]函数时遇到了非常奇怪的行为。它返回布尔类型的“@”字符,根据objective-c,该字符是错误的。如果我使用objc\runtime.h库方法,那么getTypeEncoding BOOL类型正确地表示为“B”,但是我不明白为什么它不能与更高级别的层NSMethodSignature一起工作。以下代码演示了该问题:

-(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
}
上述(至少对男性而言)打印出以下内容:

来自NSMethodSignature的布尔参数:@

来自objc/runtime.h的BOOL arg:B

我目前正在使用我自己的实现来避免这种奇怪的行为,但是我想知道我是否遗漏了什么或者这只是一个bug。我唯一的线索是BOOL是原始的,就像这样,在调用objective-c方法时不能直接使用它。但是,当我尝试检查它时,[objectiskingofclass:[NSNumber class]]返回NO

更新

好的,我已经将XCode更新到最新版本(6.1 6A1052d),情况大大改善。然而,我现在的问题是区分无符号字符编码和实布尔编码。我知道在旧版本中BOOL是作为char的typedef,但是如何实现真正的char与BOOL编码呢?我现在的结果是:

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

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

BOOL arg from NSMethodSignature: B
BOOL arg from objc/runtime.h: B
不过,对于模拟iPhone4s和真实设备iPhone5来说,这真是太棒了,我得到了:

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

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

我敢肯定,如果我检查iPhone5s,它将获得与iPhone6相同的输出(因为我认为它是关于64位体系结构的)。所以我现在的问题是如何正确地解决旧设备,如何区分它们的布尔字符?或者我应该假设如果编码为“c”,参数等于“1”,我们有是,而对于“0”,我们没有?

我从调试器中的po[inv methodSignature]中得到了以下信息:

(lldb)采购订单【投资方法签字】

<NSMethodSignature: 0x7be7f660>
    number of arguments = 3
    frame size = 12
    is special struct return? NO
    return value: -------- -------- -------- --------
        type encoding (v) 'v'
        flags {}
        modifiers {}
        frame {offset = 0, offset adjust = 0, size = 0, size adjust = 0}
        memory {offset = 0, size = 0}
    argument 0: -------- -------- -------- --------
        type encoding (@) '@'
        flags {isObject}
        modifiers {}
        frame {offset = 0, offset adjust = 0, size = 4, size adjust = 0}
        memory {offset = 0, size = 4}
    argument 1: -------- -------- -------- --------
        type encoding (:) ':'
        flags {}
        modifiers {}
        frame {offset = 4, offset adjust = 0, size = 4, size adjust = 0}
        memory {offset = 0, size = 4}
    argument 2: -------- -------- -------- --------
        type encoding (c) 'c'
        flags {isSigned}
        modifiers {}
        frame {offset = 8, offset adjust = 0, size = 4, size adjust = -3}
        memory {offset = 0, size = 1}

参数数量=3
框架尺寸=12
特殊结构是否返回?不
返回值:-------------------------------
类型编码(v)‘v’
标志{}
修饰语{}
帧{offset=0,offset adjust=0,size=0,size adjust=0}
内存{offset=0,size=0}
参数0:------------------------------
类型编码(@)@'
标志{isObject}
修饰语{}
帧{offset=0,offset adjust=0,size=4,size adjust=0}
内存{offset=0,size=4}
论据1:---------------------
类型编码(:)':'
标志{}
修饰语{}
帧{offset=4,offset adjust=0,size=4,size adjust=0}
内存{offset=0,size=4}
论据2:-------------------------
类型编码(c)‘c’
标志{isSigned}
修饰语{}
帧{offset=8,offset adjust=0,size=4,size adjust=-3}
内存{offset=0,size=1}
我用NSLog打印出来了

来自NSMethodSignature的布尔参数:c

我不能写评论,所以我写了这个答案。请您将您的[inv方法签名]?!在将NSLog分配给encFromGetArgument后,您是否可以直接输出NSLog

char *buf1 = @encode(BOOL);
NSLog(@"bool type is: %s", buf1);
在32位模拟器上,encode(BOOL)返回“c”,而在64位上,它返回“B”。在构建设置中,将架构更改为
$(ARCHS\u标准\u 32\u位)
,然后它将为您返回“c”

在objc/objc.h文件中

#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位的布尔是一种有符号字符。您可以将其与无符号字符区分开来

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

您可以从中判断设备是32位还是64位,如果是32位,则“c”对布尔检查有效。

基于@gabbler答案,我已设法检查参数是否为布尔。以下代码适用于32位和64位体系结构:

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

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

    if( 0 == strcmp(@encode(BOOL), encFromGetArgument) )
    {
        //BOOL val
        NSLog(@"arg is bool");
    }
    else
    {
        //not BOOL
        NSLog(@"arg is not bool");
    }
}

我无法回答您的问题,但是我不确定ARC将如何处理
[inv methodSignature]
返回的对象,您可以从该对象获得
常量字符*
。很明显,缓冲区在对象域内(在其管理下),因此我认为您不应该创建临时对象并以这种方式取消引用它。因为methodSignature是Objective类,所以我非常确定它在ARC下可以正常工作。然而,问题的关键是它为什么返回错误的值。很可能是使用临时对象导致了这个问题。请尝试使用非临时变量。不,使用属性存储编码也没有帮助。仍然在寻找答案。我还注意到类型const char*被编码为“r*”,这是没有文档记录的(char*确实被编码为“*”,所以我猜在这种情况下“r”代表const。很好!根据你的回答,我找到了我的解决方案。在第一篇文章中看到我的更新。我看到了,很高兴它有所帮助。