web-dev-qa-db-ja.com

パラメーターとしてのObjective-Cパスブロック

BlockFunction/Methodに渡すにはどうすればよいですか?

- (void)someFunc:(__Block)someBlockを試しましたが、役に立ちませんでした。

すなわち。 Blockの-​​typeとは何ですか?

137
Jacksonkr

ブロックのタイプは、引数と戻り値のタイプによって異なります。一般的な場合、ブロック型は関数ポインター型と同じ方法で宣言されますが、*^に置き換えます。ブロックをメソッドに渡す1つの方法は次のとおりです。

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

しかし、ご覧のとおり、これは面倒です。代わりにtypedefを使用して、ブロックタイプをクリーンにすることができます。

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

そして、そのブロックを次のようなメソッドに渡します。

- (void)iterateWidgets:(IteratorBlock)iteratorBlock;
247

この質問の最も簡単な説明は、次のテンプレートに従うことです。

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
};
54
EnriMR

これは役に立つかもしれません:

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

ブロックパラメータとしてブロックを渡すと、次のようにできます。

//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);
23
Aleksei Minaev

以下の例のс関数を使用してブロックを渡すもう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
        });
    });
}
8
Dren

該当する場合は、ブロックを単純なプロパティとして設定することもできます。

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

ブロックプロパティが「コピー」であることを確認してください。

もちろん、typedefも使用できます。

typedef void (^SimpleBlock)(id);

@property (nonatomic, copy) SimpleBlock someActionHandler;
6
iiFreeman

また、通常の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

5
gheese

私は常にブロック構文を忘れがちです。これは、ブロックを宣言する必要があるときに常に頭に浮かびます。私はそれが誰かを助けることを願っています:)

http://fuckingblocksyntax.com

3
Juan F. Sagasti

このスレッドでの答えにもかかわらず、私はブロックを関数として、パラメーターを使用する関数を書くことに本当に苦労しました。最終的に、ここに私が思いついた解決策があります。

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開発者の助けになることを願っています! (もしそうなら、この質問と私の答えに投票することを忘れないでください!)

2
Mike Gledhill

振った後にダイスの値を返すクラスのcompletionBlockを作成しました。

  1. ReturnType(.h上の@interface宣言)でtypedefを定義します

    typedef void (^CompleteDiceRolling)(NSInteger diceValue);
    
  2. ブロックの@propertyを定義します(.h

    @property (copy, nonatomic) CompleteDiceRolling completeDiceRolling;
    
  3. finishBlock.h)でメソッドを定義します

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock;
    
  4. 前に定義したメソッドを.mファイルに挿入し、finishBlockを前に定義された@propertyにコミットします

    - (void)getDiceValueAfterSpin:(void (^)(NSInteger diceValue))finishBlock{
        self.completeDiceRolling = finishBlock;
    }
    
  5. completionBlockをトリガーするには、定義済みのvariableTypeを渡します(completionBlockが存在するかどうかを確認することを忘れないでください)

    if( self.completeDiceRolling ){
        self.completeDiceRolling(self.dieValue);
    }
    
2
Alex Cio

完全なテンプレートは次のようになります

- (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 {

}
0
yoAlex5