Block
をFunction
/Method
に渡すにはどうすればよいですか?
- (void)someFunc:(__Block)someBlock
を試しましたが、役に立ちませんでした。
すなわち。 Block
の-typeとは何ですか?
ブロックのタイプは、引数と戻り値のタイプによって異なります。一般的な場合、ブロック型は関数ポインター型と同じ方法で宣言されますが、*
を^
に置き換えます。ブロックをメソッドに渡す1つの方法は次のとおりです。
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
しかし、ご覧のとおり、これは面倒です。代わりにtypedef
を使用して、ブロックタイプをクリーンにすることができます。
typedef void (^ IteratorBlock)(id, int);
そして、そのブロックを次のようなメソッドに渡します。
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
この質問の最も簡単な説明は、次のテンプレートに従うことです。
1。メソッドパラメーターとしてブロック
Template
- (void)aMethodWithBlock:(returnType (^)(parameters))blockName {
// your code
}
例
-(void) saveWithCompletionBlock: (void (^)(NSArray *elements, NSError *error))completionBlock{
// your code
}
ケースの他の用途:
2。プロパティとしてブロック
Template
@property (nonatomic, copy) returnType (^blockName)(parameters);
例
@property (nonatomic,copy)void (^completionBlock)(NSArray *array, NSError *error);
。メソッド引数としてブロック
Template
[anObject aMethodWithBlock: ^returnType (parameters) {
// your code
}];
例
[self saveWithCompletionBlock:^(NSArray *array, NSError *error) {
// your code
}];
4。ローカル変数としてブロック
Template
returnType (^blockName)(parameters) = ^returnType(parameters) {
// your code
};
例
void (^completionBlock) (NSArray *array, NSError *error) = ^void(NSArray *array, NSError *error){
// your code
};
5。typedefとしてブロック
Template
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)someFunc:(void(^)(void))someBlock;
ブロックパラメータとしてブロックを渡すと、次のようにできます。
//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);
以下の例のс関数を使用してブロックを渡すもう1つの方法。バックグラウンドおよびメインキューで何かを実行する関数を作成しました。
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
});
});
}
該当する場合は、ブロックを単純なプロパティとして設定することもできます。
@property (nonatomic, copy) void (^didFinishEditingHandler)(float rating, NSString *reviewString);
ブロックプロパティが「コピー」であることを確認してください。
もちろん、typedefも使用できます。
typedef void (^SimpleBlock)(id);
@property (nonatomic, copy) SimpleBlock someActionHandler;
また、通常のc関数構文を使用してブロックを呼び出すか、呼び出します
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
ブロックの詳細はこちら
私は常にブロック構文を忘れがちです。これは、ブロックを宣言する必要があるときに常に頭に浮かびます。私はそれが誰かを助けることを願っています:)
このスレッドでの答えにもかかわらず、私はブロックを関数として、パラメーターを使用する関数を書くことに本当に苦労しました。最終的に、ここに私が思いついた解決策があります。
JSON WebサービスのURLを取得し、このURLからいくつかのJSONデータをバックグラウンドスレッドにロードし、結果のNSArray *を呼び出し元の関数に返す汎用関数loadJSONthread
を作成したかった。
基本的に、汎用的な再利用可能な関数で、バックグラウンドスレッドの複雑さをすべて隠したかったのです。
この関数を呼び出す方法は次のとおりです。
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
に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開発者の助けになることを願っています! (もしそうなら、この質問と私の答えに投票することを忘れないでください!)
振った後にダイスの値を返すクラスの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);
}
完全なテンプレートは次のようになります
- (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 {
}