是否可以将完全形成的块(包含其所有参数的块)传递给方法,然后在该方法中执行该块?
目前我在项目中重复了这个结构:
if (//block exists)
{
if (self.returnOnMainThread)
{
dispatch_async(dispatch_get_main_queue(), ^
{
//call block here
});
}
else
{
//call block here
}
}
但理想情况下,我想将上面的代码抽象出来,形成类似于以下的方法:
- (void) reportSuccessWithBlock:(GenericBlockType)block{
if (block)
{
if (self.returnOnMainThread)
{
dispatch_async(dispatch_get_main_queue(), ^
{
block;
});
}
else
{
block;
}
}
}
编辑:
预先不知道该块的类型。
所以调用路径看起来像这样
- (void) someMethod:(void (^)(NSArray *array))success
{
//Some code here setting up the array to be passed back
[self reportSuccessWithBlock:success(array)];
}
上面的代码中有一些假设(我不知道是可能的):
答案 0 :(得分:2)
如果您在评论中有两个不同的块,则可以按如下方式合并两个块。但是,这非常hacky,你需要在调用块时检查object
的类。
- (void) reportSuccessWithBlock:(void (^) (id object, NSUInteger value)) block {
if (!block)
return;
if (self.returnOnMainThread) {
dispatch_async(dispatch_get_main_queue(), block((id)someObject, value)); // return 0 instead if there is no value
}
else {
block((id) someObject, value)); // return 0 instead if there is no value
}
}
因此,当调用块时,您需要做的就是检查类并对返回的对象执行任何操作:
- (void) someMethod {
[self reportSuccessWithBlock:^(id object, NSUInteger value) {
if ([object isKindOfClass:[NSArray class]]) {
// returned an NSArray and `value` is 0 (unset)
}
else if ([object isKindOfClass:[NSDictionary class]]) {
// returned an NSDictionary and the `value` is not 0 (unset)
}
else {
// something has gone wrong somewhere!
}
}];
}
答案 1 :(得分:1)
好的,我认为使用NSArray
参数的想法是可行的,因此您可以为您的块提供相同的签名:
typedef void ^(MYBLOCK)(NSArray *args);
将您的方法实施为:
- (void)reportSuccessWithBlock:(GenericBlockType)block
andArguments:(NSArray *)args
{
if (block != nil)
{
if (self.returnOnMainThread)
{
dispatch_async(dispatch_get_main_queue(), ^{
block(args);
});
}
else
{
block(args);
}
}
}
然后这只是一个确保正确类型的参数以正确的顺序给予块的情况(听起来微不足道,但如果你弄错了会导致各种各样的仇恨)。
MYBLOCK block1 = ^(NSArray *args) {
// I accept NSNumber, NSString, NSValue
NSAssert(args.count == 3, @"Invalid argument count");
NSNumber *arg1 = args[0];
NSString *arg2 = args[1];
NSValue *arg3 = args[2];
// Do my thing
};
并将其称为:
[someClass reportSuccessWithBlock:block1
andArguments:@[ @(1), @"Hello", @(cgpoint) ]];