我像这样用键NSString和对象块初始化NSDictionary。
NSDictionary * d =
[NSDictionary dictionaryWithObjectsAndKeys:
^ ( int p1 ){ some code }, @"a",
^ ( int p1, NSString * p2 ){ some code }, @"b",
nil];
当我检索其中一些块时,它会失败[[检索时,即
someVar = [d objectForKey:@"b"];
即使有与@"b"
相关联的对象也失败。[登录字典时,我注意到可以检索的对象存储为
__NSMallocBlock__
,失败的对象存储为__NSStackBlock__
。尽管__NSStackBlock__
似乎有效,但调试器显示它包装了nil
块。
编译器和ARC根据块的参数以不同的方式存储块。要解决此问题,请创建指向块的强指针,然后将这些指针存储在字典中,因此
blockVarA = ^ ( pars ){ some code }; // Strong pointers
blockVarB = ^ ( pars ){ some code };
NSDictionary * d =
[NSDictionary dictionaryWithObjectsAndKeys:
blockVarA, @"a",
blockVarB, @"b",
nil];
将确保全部都存储为__NSMallocBlock__
块。
首先在网站feedbackassistant.apple.com上报告您的原始代码-他们将对其进行修复的可能性很小,但无论如何请这样做。 (请随意将下面的代码作为可以正确处理的版本。)
第二,您可以使用更现代的代码:
NSDictionary * d = @{ @"a" : ^ ( int p1 ){ NSLog(@"%d", p1 * arg); },
@"b" : ^ ( int p1, NSString * p2 ){ NSLog(@"%d, '%@'"
};
Apple看起来确实可以正确编译(并且查看底层的机制和类型,可以看到为什么这与您的代码不同并且没有相同的编译器错误)。Postscript] >>[您是正确的,Apple确实会根据某些因素以不同的方式存储块-这是编译器优化,与所有此类优化一样,程序员在改进的代码(性能,大小等)中不应该看到它们。
但是出于种种原因,Apple从未解释过,他们决定发布这种对程序员可见的优化实现,并确实要求程序员添加特定的代码来对其进行处理。随着时间的流逝,他们使添加该代码成为不必要,并最终记录为“工作完成”。
[在还使用ARC的Swift中,他们似乎是从Objective-C的经验中学到的,并通过优化和语言级别的注释的组合正确地实现了块处理-有人可能会就必要性/益处/成本进行辩论/ choice / etc。后者,但是我们可以说Apple在做出选择方面并不是唯一的,并且在他们从Objective-C中的块开始的位置上肯定是一个巨大的进步。