Objective-C传递块作为参数
我怎样才能通过一个Function
/ Method
Block
?
我试过- (void)someFunc:(__Block)someBlock
无济于事。
即。 什么是一个Block
的types ?
块的types取决于其参数和返回types。 在一般情况下,块types被声明为函数指针types的相同方式,但用^
replace*
。 将块传递给方法的一种方法如下所示:
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
但是,正如你所看到的,那很乱。 您可以改为使用typedef
来使块types更清洁:
typedef void (^ IteratorBlock)(id, int);
然后将该块传递给如下所示的方法:
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
这可能有帮助:
- (void)someFunc:(void(^)(void))someBlock;
这个问题的最简单的解释是遵循这些模板:
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.作为局部variables阻止
模板
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 };
你可以这样做,传递块作为块参数:
//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);
如果适用于您,也可以将块设置为简单属性:
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
确保块属性是“复制”!
当然你也可以使用typedef:
typedef void (^SimpleBlock)(id); @property (nonatomic, copy) SimpleBlock someActionHandler;
在下面的例子中使用с函数传递块的另一种方法。 我创build了在后台和主队列中执行任何操作的函数。
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 }); }); }
你也可以使用通常的c函数语法调用或调用一个块
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{ iteratorBlock(someId, someInt); }
更多信息块在这里
尽pipe在这个线程上给出的答案,我真的很努力编写一个函数,将一个块作为一个函数 – 和一个参数。 最终,这是我提出的解决scheme。
我想写一个通用函数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 *logging:
+(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问题涉及如何调用函数,传递一个Block作为参数,所以我简化了上面的代码,并没有包含loadJSONDataFromURL
函数。
但是,如果你有兴趣,你可以在这个博客上find这个JSON加载函数的副本: http : //mikesknowledgebase.azurewebsites.net/pages/Services/WebServices-Page6.htm
希望这有助于其他XCode开发人员! (不要忘记把这个问题和我的答案投票,如果是的话)!
我总是倾向于忘记块语法。 当我需要声明一个块的时候,这总是出现在我的脑海里。 我希望它可以帮助别人:)
我给一个类写了一个completionBlock,这个类会在被撼动后返回骰子的值:
-
使用returnType定义typedef(在
@interface
声明之上的.h
)typedef void (^CompleteDiceRolling)(NSInteger diceValue);
-
为块(
.h
)定义@property
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
-
用
finishBlock
(.h
)定义一个方法- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
-
将以前定义的方法插入到
.m
文件中,@property
finishBlock
提交给之前定义的finishBlock
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{ self.completeDiceRolling = finishBlock; }
-
触发
completionBlock
将预定义的variableType传递给它(不要忘记检查completionBlock
是否存在)if( self.completeDiceRolling ){ self.completeDiceRolling(self.dieValue); }