2

我在使用名为TransitionKit(帮助您编写状态机)的库时遇到了一种情况,我想以回调的形式提供进入和退出操作。

遗憾的是,回调包含两个完全无用的参数。典型的块必须如下所示:

^void (TKState *state, TKStateMachine *stateMachine) {
    // I TOTALLY don't want parameters `state` or `stateMachine` used here
};

(这是一个匿名代码块。如果您不清楚,请在此处阅读块)

正如我在评论中指出的那样,我真的不希望在正文中提到这些参数。我试过简单地删除这个问题中建议的参数名称,如下所示:

^void (TKState *, TKStateMachine *) {
     // I foobar all I like here
};

但遗憾的是,代码将无法编译:(。

如何在代码中强制不使用参数?

4

4 回答 4

2

这是我能想到的。相当 hack 并且依赖于GCC poisonpragma,它不是标准的,而是一个 GNU 扩展——尽管,考虑到你可能clang无论如何都在编译它,它不应该是一个问题。

#define _state state
#define _stateMachine stateMachine

#pragma GCC poison state stateMachine

然后编译:

^(TKState *_state, TKStateMachine *_stateMachine) {
    do_something();
}

但这不会:

^(TKState *_state, TKStateMachine *_stateMachine) {
    do_something(state, stateMachine);
}
于 2013-08-16T11:32:14.833 回答
1

你可以有一个函数,它接受一种块,然后返回另一种块,如下所示:

@class TKState, TKStateMachine; // here so this will compile

typedef void (^LongStateBlock)(TKState *state, TKStateMachine *stateMachine);

static inline LongStateBlock Adapter(void(^block)()) {

    void(^heapBlock)() = [block copy]; // forces block to be on heap rather than stack, a one-time expense

    LongStateBlock longBlock = ^(TKState *s __unused, TKStateMachine *sm __unused) {
        heapBlock();
    };

    // this is the non-ARC, MRR version; I'll leave ARC for the interested observer
    [heapBlock release];
    return [[longBlock copy] autorelease];
}

在实践中:

// this represents a library method
- (void)takesLongStateBlock:(LongStateBlock)longBlock
{
    // which hopefully wouldn't look exactly like this
    if (longBlock) longBlock(nil, nil);
}

- (void)yourRandomMethod
{
    [self takesLongStateBlock:^(TKState *state, TKStateMachine *stateMachine) {
        NSLog(@"Gratuitous parameters, AAAAHHHH!");
    }];

    [self takesLongStateBlock:Adapter(^{
        NSLog(@"So, so clean.");
    })];

}

整个事情很重要,应该在任何类中编译。当您调用-yourRandomMethod.

于 2014-03-19T17:16:52.947 回答
0

AFAIK 在创建块时无法做你想做的事,你只能在声明块变量时错过参数名称(对块的引用,以避免误解)

所以在这里你可以错过参数名称:

void (^myBlock)(SomeClass *);

但不是在创建块时:

myBlock = ^(SomeClass *o)
{
};
于 2013-08-16T14:56:52.420 回答
0

我会写

^void (TKState *unused_state, TKStateMachine *unused_stateMachine) {
    // Anyone using unused_state or unused_stateMachine gets what they deserve.
};

当然有人可以使用参数。但是无论你做什么,他们都可以更改代码。如果有人打算朝自己的脚开枪,没有人能阻止他们。

于 2014-03-18T22:01:12.550 回答