How do I specify the block object / predicate required by NSDictionary's keysOfEntriesPassingTest?

眉间皱痕 提交于 2019-12-06 04:45:54

问题


For learning (not practical -- yet) purposes, I'd like to use the following method on an NSDictionary to give me back a set of keys that have values using a test I've defined. Unfortunately have no idea how to specify the predicate.

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

Let's say for example all my values are NSURLs, and I'd like to get back all the URLs that are on port 8080. Here's my stab at coding that -- though it doesn't really make sense to me that it'd be correct:

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

And that's because I get back the following compiler error:

incompatible block pointer types initializing 'void (^)(struct objc_object *, struct objc_object *, BOOL *)', expected 'BOOL (^)(struct objc_object *, struct objc_object *, BOOL *)'

What am I missing? I'd appreciate a pointer at some docs that go into more detail about the "Block object" that the predicate is supposed to be.
Thanks!


And this is the code that works:

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

回答1:


The error indicates that your block must return a BOOL, rather than id. Check the docs. I suspect you are expected to return YES if the key/obj pair passes the desired test.




回答2:


A little expansion on Barry's answer....

A block is just like a function pointer with one key difference. A block will infer the return type from the return statements contained within or it will give an error message like the one you said (the LLVM compiler's error should be a bit more reasonable).

When you wrote:

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

Consider that as a function:

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

See the problem? There is a code path that doesn't return a value and, thus, the compiler would complain.



来源:https://stackoverflow.com/questions/3034251/how-do-i-specify-the-block-object-predicate-required-by-nsdictionarys-keysofe

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!