如何将Block
传递给Function
/ Method
?
我试了- (void)someFunc:(__Block)someBlock
但没有用。
即。 Block
的类型是什么?
答案 0 :(得分:246)
块的类型因其参数及其返回类型而异。在一般情况下,块类型的声明方式与函数指针类型相同,但用*
替换^
。将块传递给方法的一种方法如下:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
但正如你所看到的那样,这很麻烦。您可以使用typedef
来使块类型更清晰:
typedef void (^ IteratorBlock)(id, int);
然后将该块传递给类似的方法:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
答案 1 :(得分:51)
这可能会有所帮助:
- (void)someFunc:(void(^)(void))someBlock;
答案 2 :(得分:48)
这个问题最简单的解释是遵循以下模板:
<强> 1。阻止作为方法参数
<强> 模板 强>
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
<强> 实施例 强>
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
案件的其他用途:
<强> 2。阻止作为财产
<强> 模板 强>
@property (nonatomic, copy) returnType (^blockName)(parameters);
<强> 实施例 强>
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
第3。阻止作为方法参数
<强> 模板 强>
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
<强> 实施例 强>
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
<强> 4。阻止作为局部变量
<强> 模板 强>
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
<强> 实施例 强>
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
<强> 5。阻止作为typedef
<强> 模板 强>
typedef returnType (^typeName)(parameters);
typeName blockName = ^(parameters) {
// your code
}
<强> 实施例 强>
typedef void(^completionBlock)(NSArray *array, NSError *error);
completionBlock didComplete = ^(NSArray *array, NSError *error){
// your code
};
答案 3 :(得分:23)
您可以这样做,将块作为块参数传递:
//creating a block named "completion" that will take no arguments and will return void
void(^completion)() = ^() {
NSLog(@"bbb");
};
//creating a block namd "block" that will take a block as argument and will return void
void(^block)(void(^completion)()) = ^(void(^completion)()) {
NSLog(@"aaa");
completion();
};
//invoking block "block" with block "completion" as argument
block(completion);
答案 4 :(得分:8)
在下面的示例中使用с函数传递块的另一种方法。 我已经创建了在后台和主队列中执行任何操作的函数。
blocks.h文件
void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));
blocks.m文件
#import "blocks.h"
void performInBackground(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), block);
}
void performOnMainQueue(void(^block)(void)) {
if (nil == block) {
return;
}
dispatch_async(dispatch_get_main_queue(), block);
}
在必要时导入blocks.h并调用它:
- (void)loadInBackground {
performInBackground(^{
NSLog(@"Loading something in background");
//loading code
performOnMainQueue(^{
//completion hadler code on main queue
});
});
}
答案 5 :(得分:6)
如果适用于您,您还可以将块设置为简单属性:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
确保block属性为“copy”!
当然你也可以使用typedef:
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
答案 6 :(得分:5)
您也可以使用常用的c函数语法
调用或调用块-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
有关块的更多信息
答案 7 :(得分:3)
我总是倾向于忘记块语法。当我需要声明一个块时,我总会想到这一点。我希望它可以帮助某人:)
答案 8 :(得分:2)
尽管在这个帖子上给出了答案,但我真的很难写出一个函数,它将Block作为一个函数 - 并带有一个参数。最终,这是我提出的解决方案。
我想编写一个通用函数loadJSONthread
,它将获取JSON Web服务的URL,在后台线程上从此URL加载一些JSON数据,然后将NSArray *的结果返回给调用函数。
基本上,我希望将所有后台线程复杂性隐藏在通用的可重用函数中。
以下是我将如何调用此函数:
NSString* WebServiceURL = @"http://www.inorthwind.com/Service1.svc/getAllCustomers";
[JSONHelper loadJSONthread:WebServiceURL onLoadedData:^(NSArray *results) {
// Finished loading the JSON data
NSLog(@"Loaded %lu rows.", (unsigned long)results.count);
// Iterate through our array of Company records, and create/update the records in our SQLite database
for (NSDictionary *oneCompany in results)
{
// Do something with this Company record (eg store it in our SQLite database)
}
} ];
...这就是我所挣扎的:如何声明它,以及如何在加载数据后调用Block函数,并传递Block
NSArray *加载的记录:
+(void)loadJSONthread:(NSString*)urlString onLoadedData:(void (^)(NSArray*))onLoadedData
{
__block NSArray* results = nil;
dispatch_queue_t queue = dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0);
dispatch_async(queue, ^{
// Call an external function to load the JSON data
NSDictionary * dictionary = [JSONHelper loadJSONDataFromURL:urlString];
results = [dictionary objectForKey:@"Results"];
dispatch_async(dispatch_get_main_queue(), ^{
// This code gets run on the main thread when the JSON has loaded
onLoadedData(results);
});
});
}
这个StackOverflow问题涉及如何调用函数,将块作为参数传递,因此我简化了上面的代码,而不包括loadJSONDataFromURL
函数。
但是,如果您有兴趣,可以在此博客上找到此JSON加载函数的副本: http://mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
希望这有助于其他一些XCode开发人员! (不要忘记将这个问题和我的答案投票,如果有的话!)
答案 9 :(得分:2)
我为一个类写了一个completionBlock,它会在它们被动摇之后返回骰子的值:
使用returnType(.h
声明上方@interface
)定义typedef
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
为块(@property
)
.h
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
使用finishBlock
(.h
)
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
在.m
文件中插入以前定义的方法,然后将finishBlock
提交到
@property
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
触发completionBlock
将预定义的variableType传递给它
(别忘了检查completionBlock
是否存在)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
答案 10 :(得分:0)
完整的模板看起来像
- (void) main {
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
//Execute a block
successBlock();
// failureBlock([[NSError alloc]init]);
}
- (void) successMethod {
}
- (void) failureMethod:(NSError*) error {
}