什么是nil,但在插入NSMutableDictionary时不是nil

时间:2015-04-18 18:06:30

标签: objective-c xcode6.3 ios8.3

我在iPhone 6,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

然后崩溃('对象不能为nil(key:appversion)')。

调试版本返回:

a
b
c
d
e
g
h

什么是零,但不是零?

3 个答案:

答案 0 :(得分:3)

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

.h文件有:

- (void) verifyWinner:(NSString*)baseAcctId
           appVersion:(NSString*)appVersion
           onComplete:(OnCompleteWinnerVerifier)onComplete __attribute__((nonnull));

我猜测原始开发人员希望阻止onComplete设置为nil。但是,出于某种原因,__attribute__((nonnull))与每个参数相关联。

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

此问题现在才出现在XCode 6.3中。所以,也许Apple最近添加了优化,或者引入了6.3中的一个错误,它将__attribute__与每个参数相关联,而不仅仅是它旁边的参数(无论如何都是为了优化目的)。

答案 1 :(得分:0)

检查[NSNull null]

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

https://developer.apple.com/library/mac/documentation/Cocoa/Conceptual/NumbersandValues/Articles/Null.html

答案 2 :(得分:0)

结果看起来很奇怪。这篇文章不错; google for"每个程序员应该知道未定义的行为"作者:Chris Lattner(Swift的首席开发人员,所以他应该知道他在说什么)。

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

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

因为编译器确定appVersion不是nil,最后一次测试没有完成,appVersion存储在param中,因为它是nil,你就崩溃了。