4

出于学习(尚不实用)的目的,我想在 NSDictionary 上使用以下方法,使用我定义的测试返回一组具有值的键。不幸的是不知道如何指定谓词。

NSDictionary keysOfEntriesPassingTest:
- (NSSet *)keysOfEntriesPassingTest:(BOOL (^)(id key, id obj, BOOL *stop))predicate

例如,假设我所有的值都是 NSURL,我想取回端口 8080 上的所有 URL。这是我编写代码的尝试——尽管它对我来说并没有什么意义正确的:

NSSet * mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
                 if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
                     return key;
                 }]

那是因为我得到了以下编译器错误:

初始化 'void (^)(struct objc_object *, struct objc_object *, BOOL *)' 的不兼容块指针类型,预期 'BOOL (^)(struct objc_object *, struct objc_object *, BOOL *)'

我错过了什么?我会很感激一些文档的指针,这些文档更详细地介绍了谓词应该是的“块对象”。
谢谢!


这是有效的代码:

NSSet *mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop)
{
  if ([[obj port] isEqual:[NSNumber numberWithInt: 8080]])
     return YES;
   else
     return NO;
}];
4

2 回答 2

7

对巴里的回答进行一点扩展......

块就像一个函数指针,只有一个键不同。一个块将从其中包含的 return 语句推断返回类型,或者它会给出一条错误消息,就像你说的那样(LLVM 编译器的错误应该更合理一些)。

当你写道:

NSSet * mySet = [myDict keysOfEntriesPassingTest:^(id key, id obj, BOOL *stop) {
                 if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
                     return key;
                 }]

将其视为一个函数:

BOOL bob(id key, id obj) {
    if( [[obj port] isEqual: [NSNumber numberWithInt: 8080]]) {
        return key;
    }
}

看到问题了吗?有一个不返回值的代码路径,因此编译器会抱怨。

于 2010-06-14T04:40:56.323 回答
3

该错误表明您的块必须返回 a BOOL,而不是id。检查文档。YES我怀疑如果密钥/对象对通过了所需的测试,您应该会返回。

于 2010-06-13T23:15:16.033 回答