为什么此 Objective C 代码会因 EXC_BAD_ACCESS 代码=1 而崩溃? (使用块语法和字典)

Why does this Objective C code crash with EXC_BAD_ACCESS code=1? (Uses block syntax and dicts)

//Section 1 (declarations)    

NSString *foo;
NSString *bar;

NSDictionary *foobar =
@{
    @"bar":^{return @"foo";}
 };
typedef NSString *(^barfoo)();

鉴于上述声明,为什么仅以下 Objective-C 代码的最后一行生成

EXC_BAD_ACCESS code=1

//Section 2 (crashes)

foo = foobar[@"bar"];             //no error, foo == @"foo"
bar = foobar[@"foo"];             //no error, bar == nil
foo = ((barfoo)foobar[@"bar"])(); //no error, foo == @"foo"
bar = ((barfoo)foobar[@"foo"])(); //EXC_BAD_ACCESS code=1
NSLog(@"%@%@",foo,bar);           // never runs!

我应该注意到在 try/catch 中,catch 没有捕获任何东西;没有异常被抛出。将 foobar 的内容更改为 @{@"bar":^NSString*{return @"foo";} 没有帮助。

我还应该注意以下代码 有效 并且 不会出错 :

//Alternate Section 2 (does not crash)    

barfoo foobard = foobar[@"foo"];
barfoo barfood = foobar[@"bar"];
barfood ? foo = barfood() : nil;
foobard ? bar = foobard() : nil;
NSLog(@"%@%@",foo,bar);          // Returns foo(null)

注意:代码在 iOS 9.2.1 上执行。

我很困惑为什么很困惑。

由于 foobar[@"foo"]nil(正如您的评论正确显示的那样),您不能将其视为一个块并调用它。这就是 ((barfoo)foobar["@foo"])() 崩溃的原因。

当第二个代码段检测到您从字典中获得的对象是 nil 时,它根本不调用任何东西,因此它对 foobar[@"foo"][= 的 return 没有任何作用17=]

关于 try catch - 它不会抛出错误,它 崩溃 。那是不同的东西。程序无法恢复的东西。您作为开发人员必须确保不会发生的事情。您的工作是确保您尝试调用的块实际上是非 nil.