2

我遇到了一種情況,使用一個名爲TransitionKit(幫助您編寫狀態機)的庫,我希望以回調的形式提供進入和退出操作。如何強制匿名塊的參數在Objective-C中未被使用?

不幸的是,回調包括兩個完全無用的參數。一個典型的塊有看起來像這樣:

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

(這是一個匿名代碼塊閱讀上塊here如果你還不清楚。)

正如我在評論所指出的那樣,我真的不希望那些在體內提及的參數。我試着簡單地刪除了參數的名字,如建議在this question像這樣:

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

但遺憾的代碼將無法再編譯:(

我怎麼能強制執行的參數這種非使用情況?代碼

回答

2

這是我能想出相當多的黑客,並且依賴於GCC poison編譯,這不是標準,但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); 
} 
+0

我還沒有用'clang'自己試過,但我相信它可能會起作用。它似乎不是一個通用的解決方案:/ – fatuhoku

0

AFAIK有沒有辦法做你想要什麼,當你創建一個塊,你只能錯過當你聲明一個塊變量時的參數名稱(對塊的引用,以避免誤解)

所以在這裏你可能會錯過參數名稱:

void (^myBlock)(SomeClass *); 

但不是當你創建一個塊:

myBlock = ^(SomeClass *o) 
{ 
}; 
0

我會寫

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

當然有人可以使用的參數。但是,無論你做什麼,他們都可以更改代碼。如果有人打算在腳下自己射擊,那麼就不會阻止他們。

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."); 
    })]; 

} 

整個事情是gisted,並應在任何課堂內編譯。當您撥打-yourRandomMethod時,它會達到您的預期。

相關問題