Is it possible to create a block variable as selector accepting parameters, and to pass it to performSelector:withObject:? Currently, writing some tests and want to write a self contained method with all related checking. Need to pass a block, receive the param in it and do some checking in that block. I'm looking for something like:
...
SEL blockAsSelector = ^{(NSString *param){NSLog(@"Passed param = %@", param);}}
[self performSelector:blockAsSelector withObject:stringThatWillBeUsedAsParamInBlock];
...
Is it possible to create a block variable as selector accepting parameters, and to pass it to performSelector:withObject:?
No. Blocks and selectors are not the same thing.
In your example, it doesn't make sense. -performSelector:withObject:
runs synchronously on the same thread. You might as well just execute the block i.e.
void (^myBlock)(NSString*) = ^(NSString *param){NSLog(@"Passed param = %@", param);};
myBlock(@"foo");
If you want to do the work in the block concurrently, you would use GCD or am NSBlockOperation.
If you don't need a delay to perform the operation you can:
[[NSOperationQueue mainQueue] addOperationWithBlock:^(void)block]
I generally agree with other answers that you should try to find another way to do this, as selectors and blocks are really not that interchangeable. But if you absolutely had to do it this way, I think something like this would be your best bet:
// BlockWrapper.h
@interface BlockWrapper : NSObject
@property(nonatomic, retain) void (^block)(NSString*);
@property(nonatomic, copy) NSString* string;
@end
// Your other code file
- (void)evaluateBlockWrapper:(BlockWrapper)wrapper {
wrapper.block(wrapper.string);
}
...
BlockWrapper* wrapper = [[BlockWrapper alloc] init];
wrapper.block = ^(NSString* param) { NSLog(@"Passed param = %@", param); }
wrapper.string = stringThatWillBeUsedAsParamInBlock;
[self performSelector:@selector(evaluateBlockWrapper:) withObject:wrapper];
...
Although this makes me wonder why you want to have the block take a string parameter, instead of just referencing the string inside the block:
// Your other code file
- (void)evaluateBlock:(void (^)(void))block {
block();
}
...
[self performSelector:@selector(evaluateBlock:)
withObject:^{
NSLog(@"Passed param = %@", stringThatWillBeUsedAsParamInBlock);
}];
...
I'm not too sure about all the memory management here, so someone else will have to double check me on that.