Objective-C 传递块作为参数

如何将 Block传递给 Function/Method

我试了 - (void)someFunc:(__Block)someBlock,但没有用。

Block类型是多少?

105545 次浏览

块的类型取决于它的参数和返回类型。在一般情况下,块类型的声明方式与函数指针类型相同,但是用一个 ^代替了 *。将块传递给方法的一种方法如下:

- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;

但是正如你所看到的,这是混乱的。你可以使用 typedef来使代码块类型更清晰:

typedef void (^ IteratorBlock)(id, int);

然后将该块传递给一个方法,如下所示:

- (void)iterateWidgets:(IteratorBlock)iteratorBlock;

这可能会有所帮助:

- (void)someFunc:(void(^)(void))someBlock;

还可以使用通常的 c 函数语法调用块

-(void)iterateWidgets:(IteratorBlock)iteratorBlock{


iteratorBlock(someId, someInt);
}

更多街区信息请点击这里

Http://developer.apple.com/library/ios/#documentation/cocoa/conceptual/blocks/articles/bxgettingstarted.html#//apple_ref/doc/uid/tp40007502-ch7-sw1

你也可以将 block 设置为一个简单的属性,如果它适用于你的话:

@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);

确保块属性为“ copy”!

当然你也可以使用 typedef:

typedef void (^SimpleBlock)(id);


@property (nonatomic, copy) SimpleBlock someActionHandler;

您可以这样做,将 block 作为 block 参数传递:

//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);

使用下面的例子中的函数传递块的另一种方法。 我已经创建了在后台和主队列中执行任何操作的函数。

H 文件

void performInBackground(void(^block)(void));
void performOnMainQueue(void(^block)(void));

文件

#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);
}

当需要时,调用 import block. h:

- (void)loadInBackground {


performInBackground(^{


NSLog(@"Loading something in background");
//loading code


performOnMainQueue(^{
//completion hadler code on main queue
});
});
}

尽管在这个线程中给出了答案,但我真的很难写出一个将 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 问题涉及到如何调用函数,将 Block 作为参数传递,因此我简化了上面的代码,没有包含 loadJSONDataFromURL函数。

但是,如果您感兴趣,您可以在这个博客上找到这个 JSON 加载函数的副本: Http://mikesknowledgebase.azurewebsites.net/pages/services/webservices-page6.htm

希望这对其他 XCode 开发人员有所帮助! (如果有的话,别忘了给这个问题和我的答案投票!)

我为一个类编写了一个补全块,它将在骰子被摇动后返回它们的值:

  1. 使用 rereturn Type 定义 typedef (@interface声明之上的 .h)

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
  2. Define a @property for the block (.h)

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
  3. Define a method with finishBlock (.h)

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
  4. Insert previous defined method in .m file and commit finishBlock to @property defined before

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
    self.completeDiceRolling = finishBlock;
    }
    
  5. To trigger completionBlock pass predefined variableType to it (Don't forget to check whether the completionBlock exists)

    if( self.completeDiceRolling ){
    self.completeDiceRolling(self.dieValue);
    }
    

我总是倾向于忘记块语法。当我需要声明一个块时,我总是会想到这个问题。我希望这对某人有所帮助:)

Http://fuckingblocksyntax.com

对这个问题最简单的解释是遵循以下模板:

块作为方法参数

模板

- (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);

块作为方法参数

模板

[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
};

完整的模板看起来像

- (void) main {
//Call
[self someMethodWithSuccessBlock:^{[self successMethod];}
withFailureBlock:^(NSError * error) {[self failureMethod:error];}];
}


//Definition
- (void) someMethodWithSuccessBlock:(void (^) (void))successBlock
withFailureBlock:(void (^) (NSError*))failureBlock {
    

//Execute a block
successBlock();
failureBlock([[NSError alloc]init]);
}


- (void) successMethod {
}


- (void) failureMethod:(NSError*) error {
}