【问题标题】:NSNumber Literals BOOL reverse cause objCType type change?NSNumber Literals BOOL 反向导致 objCType 类型改变?
【发布时间】:2014-08-27 15:39:12
【问题描述】:

我在下面测试这些代码:

BOOL b1 = YES;
BOOL b2 = NO;
BOOL b3 = !b1;

NSNumber *num1 = @(b1);
NSNumber *num2 = @(b2);
NSNumber *num3 = @(b3);
NSNumber *num4 = @(!b1);

num1,num2,num3的objCType([num1 objCType])类型是“c”,但是num4的objcType是“i”。为什么我把bool倒过来,NSNumber的objcType就变了?

============================

我的问题是,我的原始代码是这样的:

BOOL *m_bFirstEvent;
[pDict setValue:**@[[NSNumber numberWithBool:!m_bFristEvent]]** forKey:@"params"];
NSData *pPostData = [NSJSONSerialization dataWithJSONObject:pDict options:0 error:&pError];
the json string is 
{"method":"getEvent", "id":7, "params":[false]}

在我使用XCode的refactor->“转换为现代Objective-c语法”之后,代码变为:

BOOL *m_bFirstEvent;
[pDict setValue:**@[@(!m_bFristEvent)]** forKey:@"params"];
NSData *pPostData = [NSJSONSerialization dataWithJSONObject:pDict options:0 error:&pError];
the json string is 
{"method":"getEvent", "id":7, "params":[0]}

我怎样才能避免这个 NSNumber Literals 错误并安全地使用 XCode 的 refactor->"convert to modern Objective-c syntax" for NSNumber Literals?

【问题讨论】:

    标签: objective-c boolean nsnumber


    【解决方案1】:

    大多数时候,人们并不关心 NSNumber 是否包含一个 BOOL 值,或者一个值为 0 或 1 的整数。当您创建 JSON(并且可能在您处理 JSON 时)时,您会关心。

    只有 [NSNumber numberWithBool:xxx] 或 [[NSNumber alloc] initWithBool:xxx] 创建一个 NSNumber,它将在 JSON 中转换为 true 或 false(而不是 1 或 0)。如果您使用@YES、@NO 或@(xxx),其中xxx 的类型为BOOL,则相同,因为所有这些最终都会调用initWithBool。因此,就您而言,不幸的是,Apple 的转换工具做错了事。

    实际上只有两个包含布尔值的 NSNumber 对象存在(显然一个用于@YES,一个用于@NO)。所以如果你处理JSON,你可以检查例如

    if (jsonResult == @YES)
        NSLog (@"json data contained the value 'true'");
    else if (jsonResult == @NO)
        NSLog (@"json data contained the value 'false'");
    else if ([jsonResult isKindOfClass:[NSNumber class]])
        NSLog (@"json data contained some kind of number");
    

    这将区分真假,以及0、1或其他值。是的,与 == 的比较是故意进行的并且是正确的。

    @ ((BOOL) xxx)
    

    将创建一个带有布尔值的 NSNumber。例如

    @ ((BOOL) ! myBoolValue)
    @ ((BOOL) (x >= 0 && x <= 100)
    

    等等。似乎有时BOOL是有符号的char,有时是bool。如果你写,那会有所不同

    @ ((BOOL) 256) // May be @YES or @NO, depending on target
    @ ((BOOL) 0.3) // May be @YES or @NO, depending on target
    

    同样,转换为 bool 而不是 BOOL 可能会也可能不会创建 numberWithBool。两者都有

    @ ((BOOL) (bool) 256)
    @ ((BOOL) (bool) 0.3)
    

    将产生值@YES,因为转换为 bool 如果值非零则产生 1,如果值为零则产生 0; this 也可以与 C 指针或对象指针一起使用。

    【讨论】:

      【解决方案2】:

      我相信是由于 C 的规则,所有输入和计算小于 int 数据类型的中间结果都是整数。因此,在 BOOL 类型上使用 !(或其他运算符)会生成一个 int。

      【讨论】:

      • 那么,我怎样才能安全地将其反转并放入 NSNumber?
      • 您可以直接转换:NSNumber *num4 = @((BOOL)!b1);,尽管将其存储为整数并不是“不安全”的。即使使用您发布的代码,您仍然可以说[num4 boolValue]
      【解决方案3】:

      这是因为如果您查看BOOL 的定义,您会发现BOOLsigned char。事实上,你不能否定签名字符,这意味着它被转换为int,然后否定就消失了。

      编辑

      bool 定义现在略有不同:对于 64 位设备,它直接转换为 bool。来自objc.h文件:

      #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
      

      【讨论】:

        猜你喜欢
        • 1970-01-01
        • 1970-01-01
        • 1970-01-01
        • 2018-07-14
        • 2016-08-30
        • 2021-11-19
        • 1970-01-01
        • 2022-10-23
        • 1970-01-01
        相关资源
        最近更新 更多