3

ブロックベースのコールバックについてよく理解していません。私が知っているアプローチは2つあるようですが、どちらを使用すればよいかわからないので、誰かが2つの違いを説明してくれ、訂正して、必要に応じてヒントを教えてください。どれか。

私がstackoverflowから見つけたいくつかのコードと、他の場所からのライブラリなので、このコードを書いた人たちに感謝します。

typedef void (^MyClickedIndexBlock)(NSInteger index);
@interface YourInterface : YourSuperClass
@property (nonatomic, strong) MyClickedIndexBlock clickedIndexBlock

.m
//where you have to call the block
if (self.clickedIndexBlock != nil) {self.clickedIndexBlock(buttonIndex)};

// where you want to receive the callback
alert.clickedIndexBlock = ^(NSInteger index){NSLog(@"%d", index);};

上記についての私の理解は次のとおりです。

  1. MyClickedIndexBlockは、NSIntegerに対するtypedefです。MyClickedIndexBlockタイプの「clickedIndexBlock」という名前で作成されたプロパティ(clickedIndexBlockは数値にすることができます)。

  2. ブロックはメソッドとしても使用できるため、self.clickedIndexBlock(buttonIndex);を呼び出すことができます。

しかし、@ propertyとしてのこのアプローチは、実際には1つのパラメーターしかサポートしていないことがわかります。NSInteger。

一方、次のアプローチでは複数のパラメーターを使用できます。

bluetoothMe.h

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);

- (void)hardwareResponse:(hardwareStatusBlock)block;

bluetoothMe.m

- (void)hardwareResponse:(hardwareStatusBlock)block {
privateBlock = [block copy]; 
}

- (void)centralManager:(CBCentralManager *)central didConnectPeripheral:(CBPeripheral *)peripheral {
NSLog(@"Did connect to peripheral: %@", peripheral);

privateBlock(peripheral, BLUETOOTH_STATUS_CONNECTED, nil);

NSLog(@"Connected");
[peripheral setDelegate:self];
[peripheral discoverServices:nil];
 }

強力なプロパティを作成して[ブロックコピー]を実行すると、アプリが終了するまでブロックが保持されることを理解しています。したがって、[ブロックコピー]と強力な両方が保持されます。[ブロックコピー]はブロックに適用されて保持されます。そうしないと、メソッドがスコープ外になったときにブロックが消えてしまいます。

ViewController.m

[instance hardwareResponse:^(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error) {

    if (status == BLUETOOTH_STATUS_CONNECTED)
    {
        NSLog(@"connected!");
    }
    else if (status == BLUETOOTH_STATUS_FAIL_TO_CONNECT)
    {
        NSLog(@"fail to connect!");
    }
    else
    {
        NSLog(@"disconnected!");
    }

    NSLog(@"CBUUID: %@, ERROR: %@", (NSString *)peripheral.UUID, error.localizedDescription);
}];

それで、私の質問が何であったかを見てみましょう:

1)2番目のアプローチよりも最初のアプローチを選択するのはいつですか?その逆もありますか?

2)最初の例では、ブロックはプロパティのtypedefでした。2番目の例では、ブロックがメソッドとして宣言されました。最初の例をメソッドとして宣言できなかったのはなぜですか。また、2番目の例をプロパティのtypedefにできないのはなぜですか。

3)ブロックベースのコールバックが必要なすべてのタイプのデリゲートメソッドに対してtypedefを作成する必要がありますか?

4)現在、iveは1つのデリゲートメソッドのみがサポートされていることを確認しました。類似していない複数のデリゲートメソッドでブロックベースのコールバックを作成する場合に、各アプローチを実装する方法の例を教えてください。

フィードバックに感謝します。これは時々難しいです。私が得ることができる限り多くの助けが必要です。ありがとう、

ベン

4

3 に答える 3

7

質問

  • typedefブロックするかどうかにかかわらず、
  • ブロックにプロパティを使用するかどうか、
  • ブロックに単一または複数の引数があるかどうか、

完全に独立している(または直交している)。すべての組み合わせが可能であり、許可されています。

void (^myClickedIndexBlock)(NSInteger index);

myClickedIndexBlock整数引数を取り、voidを返すブロック変数を宣言します。typedefプログラムで同じブロックタイプが繰り返し発生する場合に使用できます。

// Define MyClickedIndexBlock as *type* of a block taking an integer argument and returning void:
typedef void (^MyClickedIndexBlock)(NSInteger index);
// Declare myClickedIndexBlock as a *variable* of that type:
MyClickedIndexBlock myClickedIndexBlock;

複数の引数がある場合:

void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);

また

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
hardwareStatusBlock privateBlock;

(インスタンス)変数の代わりに、プロパティを使用できます。最初の例では:

@property (nonatomic, copy) void (^myClickedIndexBlock)(NSInteger index);

ブロックプロパティとして宣言myClickedIndexBlockし、と同等です

typedef void (^MyClickedIndexBlock)(NSInteger index);
@property (nonatomic, copy) MyClickedIndexBlock clickedIndexBlock;

あなたの仮定に反して、ブロックのプロパティは単一の引数を持つブロックに制限されていません。typedefの有無にかかわらず、2番目の例でもプロパティを使用できます。

@property (nonatomic, copy) void (^privateBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);

また

typedef void (^hardwareStatusBlock)(CBPeripheral *peripheral, BLUETOOTH_STATUS status, NSError *error);
@property (nonatomic, copy) privateBlock;

ブロックにインスタンス変数またはプロパティのどちらを使用するかはあなたの選択です。プロパティを使用します(「copy」属性を使用)。

typedefを使用するかどうかは、純粋に好みの問題です。プログラムで同じブロックタイプが繰り返し発生する場合は、エラーを回避するのに役立ちます。一方、Xcodeのオートコンプリートは、typedefがなくてもうまく機能するようです(私の経験では)。

于 2013-03-11T09:51:07.247 に答える
3

ブロックプログラミングガイドを読むことを強くお勧めします。

ブロックはメソッドではありません。概念の概要で述べられていることを言い換えるつもりはありませんが、いくつかの部分を引用するだけです。

ブロックは通常、小さな自己完結型のコードを表します。[...]
後でメソッド実装のコンテキストで実行される呼び出しの時点で、コードを記述できます。

構文に混乱しているようです。

typedef void (^MyClickedIndexBlock)(NSInteger index);

基本的には、NSInteger型の単一のパラメーターを取り、何も返さない(void)ブロックを表すMyClickedIndexBlockという名前の型を定義するだけです。NSIntegerのtypedefではあり
ません。

@property (nonatomic, strong) MyClickedIndexBlock clickedIndexBlock

MyClickedIndexBlockを含むプロパティの宣言です。
typedefブロックは必要ありません、書くことは完全に有効です

@property (nonatomic, strong) void(^clickedIndexBlock)(NSInteger index);

ただし、わかりやすくする(または再利用する)ために、typedefを選択することもできます。プロパティ名は。の後に続くことに注意してください^

例で呼び出すことができるため、ブロックをメソッドとして使用できると述べていself.clickedIndexBlock(buttonIndex)ます。clickedIndexBlockしかし実際には、そのように呼び出すことができるという名前のプロパティを宣言したためです。

あなたの質問にはたくさんありますが、大部分は混乱と誤解によるものです。あなたが言及する2つのアプローチは実際には違いはありません。ブロックはオブジェクトであり、NSStringや他の種類のオブジェクトの場合と同じように、パラメーター、ローカル変数、またはivars/プロパティとして操作できます。

于 2013-03-11T09:51:53.380 に答える
0

1)ブロックは整数にtypedefされていません。voidを返すのはtypedefであり、整数パラメーターを持っています。精神1または方法2に利点はありません。宣言されている場合、両方とも複数のパラメーターを持つことができます。

2)どちらの場合もその形式が選択された理由はありません。どちらも同じ結果を達成しますが、最初の結果はおそらく意味的に優れています。

3)いいえ。ブロックをメソッドにインラインで宣言できます。[NSArray enumerateObjectsUsingBlock:]インラインブロック宣言の例については、ヘッダーを参照してください。

4)複数のプロパティを作成し、必要に応じてそれぞれの個別のブロックを呼び出すことができます。

于 2013-03-11T09:55:08.603 に答える