Warning: file_get_contents(/data/phpspider/zhask/data//catemap/5/objective-c/25.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
Objective c 插入NSMutableDictionary时,什么是nil,但不是nil_Objective C_Xcode6.3_Ios8.3 - Fatal编程技术网

Objective c 插入NSMutableDictionary时,什么是nil,但不是nil

Objective c 插入NSMutableDictionary时,什么是nil,但不是nil,objective-c,xcode6.3,ios8.3,Objective C,Xcode6.3,Ios8.3,我在iPhone6、iOS 8.3上遇到了一些奇怪的行为 appVersion是传入的NSString*参数 NSLog(@"A:%@:%d",appVersion,(int)appVersion.length); if (!appVersion) NSLog(@"a"); if (appVersion == 0) NSLog(@"b"); if (appVersion == nil) NSLog(@"c"); if (appVersion == NU

我在iPhone6、iOS 8.3上遇到了一些奇怪的行为

appVersion是传入的NSString*参数

  NSLog(@"A:%@:%d",appVersion,(int)appVersion.length);
  if (!appVersion)
    NSLog(@"a");
  if (appVersion == 0)
    NSLog(@"b");
  if (appVersion == nil)
    NSLog(@"c");
  if (appVersion == NULL)
    NSLog(@"d");
  if (appVersion == Nil)
    NSLog(@"e");
  if ([appVersion isEqual:[NSNull null]])
    NSLog(@"f");

  NSString* av = [NSString stringWithFormat:@"%@",appVersion];
  if ([av isEqualToString:@"(null)"])
    NSLog(@"g");
  if (((int)appVersion) == 0)
    NSLog(@"h");

  if (appVersion) {
    NSLog(@"B:%@:%d",appVersion,(int)appVersion);
    params[@"appversion"] = appVersion;
  }
应用程序的发布版本将返回:

A:(null):0
g
h
B:(null):0
然后崩溃('object不能为nil(key:appversion)')

调试生成将返回:

a
b
c
d
e
g
h

什么是nil,但不是nil?

检查[NSNull]

NSNull类定义了一个单例对象,用于在禁止将nil作为值的情况下(通常在集合对象(如数组或字典)表示null值


结果看起来很奇怪。有一篇很好的文章;谷歌为克里斯·拉特纳(Swift的首席开发者,所以他应该知道他在说什么)的“每个程序员都应该知道的未定义行为”

看起来,在第一条NSLog语句之后,优化编译器决定appVersion不可能为nil,因为将nil传递给NSLog将是未定义的行为。这就解释了为什么不打印a到e

打印“h”,因为appVersion是一个64位指针,int只有32位,所以将非nil appVersion转换为int的结果可能是零。即使确定appVersion不是零,Optimizer也无法删除该检查


因为编译器确定appVersion不是nil,最后一个测试没有完成,appVersion被存储到param中,因为它是nil,所以崩溃

我正在处理一些遗留代码,没有注意到.h和.m文件之间的方法签名有差异

.h文件具有:

- (void) verifyWinner:(NSString*)baseAcctId
           appVersion:(NSString*)appVersion
           onComplete:(OnCompleteWinnerVerifier)onComplete __attribute__((nonnull));
我猜最初的开发人员希望防止onComplete被设置为nil。但是,由于某些原因,
\uuuuu属性((非空))
与每个参数相关联

由于
\uuuu属性\uuuu
标记,XCode正在优化所有的!=nil检查发布版本,导致崩溃



这个问题直到现在才在XCode 6.3中出现。因此,也许苹果最近添加了优化,或者在6.3中引入了一个bug,该bug将
\uuuuuu属性\uuuuuuuu>与每个参数关联,而不仅仅是它旁边的参数(出于优化目的)。

如何为appVersion???@BC uDilum分配值,它正在从couchbase文档返回的NSDictionary中提取。您也可以添加该代码吗?@Cristik它在某种程度上是一个iOS应用程序,但appVersion没有重置;它已经是0的某个版本了,很难想象有另一个线程100%地正好在if和set之间运行。Log
appVersion class
NSNull是我上面的“f”检查。在这两个版本中,它都返回NO。很抱歉,遗漏了。。。根据苹果公司的说法,尝试使用==,这会有所不同:“NSNull实例在语义上等同于nil,但也要注意它不等于nil。要测试null对象值,因此必须进行直接对象比较。”给出编译时警告:比较不同的指针类型('NSString*'和'NSNull*')好的,我将字符串转换为id,但它仍然返回NO。如果在log语句中放置断点,如果打印变量,您会得到什么样的信息?我实际上刚刚意识到它不能是[NSNull-null],因为在插入字典时这不会给您带来问题。但是将nil传递给NSLog是有定义的。它只是显示为0到t他给了一个格式说明符。好的,我算出了。我很快会给出一个答案。但是,这是正确的路径。很好。因此,如果一个参数被声明为非null,你甚至不能在运行时检查它,因为检查被优化编译器删除。换句话说,将nil传递给一个非null参数是未定义的行为。@gnasher729是的,如果它的与每个参数相关联,这可能会导致很多问题。我可能应该提交一份错误报告。很好的发现。一定要发送一份错误报告,其中包含一段简单的可复制代码来演示问题。我认为这都是有意为之的行为。请查看这篇相关文章。特别是,他指出show的意思是“所有指针参数都不能为null”,这是多么令人困惑。他还提到clang最近“开始考虑违反_属性_((非null))契约是未定义的行为”这就解释了为什么你现在看到这个。@JesseRusak是的,我认为你是对的。我只是发现语法中包含了参数号。所以,在这种情况下,它应该被定义为uuu属性uuu((非空(3)))。