【问题标题】:Method that returns block返回块的方法
【发布时间】:2015-05-31 17:19:16
【问题描述】:

我写了一个可以与点符号一起使用的方法,使用块技巧

- (RaginiDBQuery *(^)(id object))where;

可以使用点表示法调用此方法,因为它基本上不接收任何参数,(它确实接收,但使用返回的块)

所以我可以这样称呼它:

query.where(object)

我需要它而不是获得id object 我想在这种方法中收到类似的东西:

- (NSEnumerator *)where:(BOOL (^)(id object))predicate;

这个方法可以这样调用:

[object where:^(id a){return [a intValue]%2 == 1}];

我想要将两者结合起来,使用点符号调用我的方法where,但是像上面的示例一样向它发送一个谓词块,我尝试了这个:

- (RaginiDBQuery *(^)(BOOL (^)(id object))where;

但这给了我错误,所以问题是这样的:

我如何声明一个块,它需要一个块?

编辑:

对于任何在下面寻找答案检查的人,但这里是 tl;dr

- (RaginiDBQuery *(^)(BOOL(^filterBlock)(id object)))where;

【问题讨论】:

  • 我认为你只需要更多的括号:- (NSObject *(^)(BOOL(^)(id))) where 对你有用吗?例如,将通过self.where(^BOOL(id obj) {return false;}); 调用
  • @luk2302 就像一个魅力!谢谢。
  • 事实上我认为你的整个错误只是缺少一个右括号!?
  • 是的,确实如此!有时我会犯愚蠢的错误。
  • 我补充说,作为最终未来读者的答案。

标签: ios objective-c cocoa-touch objective-c-blocks


【解决方案1】:

唯一的错误基本上是缺少右括号。正确的方法应该写成:

- (RaginiDBQuery *(^)(BOOL(^)(id))) where;

稍后可以通过

self.where(^BOOL(id obj) {return [obj intValue] % 2 == 1;});

为了便于阅读,强烈建议按照 rob 的建议使用 typedef,否则很难理解要传入什么以及从函数返回什么。

【讨论】:

  • 但是我还有一个问题,如果我想保存我得到的块,是不是我无法命名或检索它?
  • 我不明白你在问什么 - 你想保存、检索或重命名什么?!
  • 例如在这个简单的方法- (void)doSomething:(void (^) (BOOL success))connectionBlock 中,我使用它的名称获取块,然后我可以稍后使用connectionBlock() 调用它,无论如何我可以在您发布的方法中获取块?
  • 想通了,应该这样使用:- (RaginiDBQuery *(^)(BOOL(^filterBlock)(id object)))where
  • 好的,现在我知道你想做什么了 ;)
【解决方案2】:

首先,你在做坏事。你应该把你的困难当作它是一个被误导的目标的证据。 Objective-C 不是 C# 或 Java 甚至 Swift。这是Objective-C。如果您想在 iOS 上使用点表示法来调用函数,请使用 Swift。不要试图将 Objective-C 锤入其他语言的模式。

其次,使用typedefs。

#import <Foundation/Foundation.h>

typedef BOOL (^MyObject_wherePredicate)(id object);
typedef NSEnumerator *(^MyObject_whereReturn)(MyObject_wherePredicate);

@interface MyObject: NSObject

- (MyObject_whereReturn)where;

@end

@implementation MyObject

- (MyObject_whereReturn)where {
    return ^(MyObject_wherePredicate predicate) {
        NSArray *array = @[ @"hello", @"world", @"this", @"is", @"a", @"test" ];
        NSPredicate *p = [NSPredicate predicateWithBlock:^BOOL(id evaluatedObject, NSDictionary *bindings) {
            return predicate(evaluatedObject);
        }];
        return [array filteredArrayUsingPredicate:p].objectEnumerator;
    };
}

@end

int main(int argc, const char * argv[])
{
    @autoreleasepool {
        MyObject *it = [[MyObject alloc] init];
        NSEnumerator *e = it.where(^(id object){
            NSString *string = object;
            return [string containsString:@"s"];
        });
        for (NSString *item in e) {
            NSLog(@"%@", item);
        }
    }
    return 0;
}

输出:

2015-05-31 12:34:31.191 commandline[1881:82976] this
2015-05-31 12:34:31.192 commandline[1881:82976] is
2015-05-31 12:34:31.192 commandline[1881:82976] test

【讨论】:

  • 嗨,罗伯,感谢您的帮助!我知道我正在做一些我在技术上不应该做的事情,但是,在我看来,对于我的特定目标,这是实现我正在寻找的更好的方法。
【解决方案3】:

先声明一个块怎么样?

BOOL (^myPredicate)(id) = ^BOOL(a)
{
    return [a intValue]%2 == 1;
}

然后像这样声明你想要的方法

- (RaginiDBQuery *(^)(myPredicate predicate))where;

【讨论】:

    猜你喜欢
    • 2018-10-08
    • 2012-11-26
    • 2015-06-30
    • 1970-01-01
    • 2015-02-12
    • 2014-04-30
    • 1970-01-01
    • 1970-01-01
    • 1970-01-01
    相关资源
    最近更新 更多