/ Block
にa を渡すにはどうすればよいですか?Function
Method
- (void)someFunc:(__Block)someBlock
無駄に試しました。
すなわち。何であるタイプのためにはBlock
?
/ Block
にa を渡すにはどうすればよいですか?Function
Method
- (void)someFunc:(__Block)someBlock
無駄に試しました。
すなわち。何であるタイプのためにはBlock
?
回答:
ブロックのタイプは、その引数と戻り値のタイプによって異なります。一般的な場合では、ブロックタイプは、関数ポインタ型である同じように宣言されているが、交換*
で^
。ブロックをメソッドに渡す1つの方法は次のとおりです。
- (void)iterateWidgets:(void (^)(id, int))iteratorBlock;
しかし、ご覧のとおり、これは厄介です。代わりにa typedef
を使用してブロックタイプをよりクリーンにすることができます。
typedef void (^ IteratorBlock)(id, int);
次に、そのブロックを次のようなメソッドに渡します。
- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
NSNumber *
か、std::string&
または他の何かあなたが関数の引数として渡すことができます。これはほんの一例です。(で置き換えることid
を除いて同等のブロックのNSNumber
場合、typedef
はになりますtypedef void (^ IteratorWithNumberBlock)(NSNumber *, int);
。)
NS_NOESCAPE
、しかしenumerateObjectsUsingBlock
、私は非エスケープされたと聞いてい、まだ私は見ていないNS_NOESCAPE
サイト内のどこにでも、またアップルのドキュメント内のすべてに言及したエスケープされます。手伝ってくれますか?
この質問の最も簡単な説明は、次のテンプレートに従ってください。
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
};
これは役に立つかもしれません:
- (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
});
});
}
また、通常のc関数構文を使用してブロックを呼び出したり呼び出したりします
-(void)iterateWidgets:(IteratorBlock)iteratorBlock{
iteratorBlock(someId, someInt);
}
ブロックの詳細はこちら
私は、振られた後にサイコロの値を返すクラス用のcompletementBlockを書きました:
returndefでtypedefを定義します(.h
上記の@interface
宣言)
typedef void (^CompleteDiceRolling)(NSInteger diceValue);
@property
ブロックのを定義します(.h
)
@property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
finishBlock
(.h
)でメソッドを定義する
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
前の定義されたメソッドInsert .m
ファイルとコミットfinishBlock
する@property
前に定義されました
- (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
self.completeDiceRolling = finishBlock;
}
completionBlock
事前定義されたvariableType をトリガーに渡すには(completionBlock
存在するかどうかを確認することを忘れないでください)
if( self.completeDiceRolling ){
self.completeDiceRolling(self.dieValue);
}
このスレッドで与えられた答えにもかかわらず、私は本当に、ブロックを関数として、そしてパラメーターを指定して、関数を書くのに苦労しました。結局、これが私が思いついた解決策です。
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
ロードされたレコードの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開発者に役立つことを願っています!(もしそうなら、この質問と私の答えに投票することを忘れないでください!)
完全なテンプレートは次のようになります
- (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 {
}