2

ブロックについて読んだところですが、ブロックは通常の方法で情報をカプセル化しているだけで、独自の強力な参照データを使用していることを理解しました。ブロックの良い使い方は何だろう?

4

3 に答える 3

11

これは、私のプロジェクトに適用されたブロックの使用法です。デリゲートとプロトコルを置き換える (特定の状況で)。

問題

サーバーからデータを非同期にロードする必要があるとします。パス (データを含む) に PUT する必要があるメソッドがあり、最終的にタスクが完了すると、メソッドの呼び出し元に結果が送信されます。

デリゲートとプロトコル ソリューション

クライアントからのメソッド シグネチャは次のAppClientとおりです。

- (void)putToPath:(NSString *)path withData:(id)data;

このメソッドは非同期であるため、戻り値にデータを含めることはできません (つまり、次のコード行を実行するなど、他のことを行うためにタスクが完了するのを待ちません)。代わりに、プロトコルを構築します。

@protocol AppClientRequestDelegate
- (void)appClient:(AppClient *)appClient didPutToPath:(NSString *)path withData:(id)sentData andReturnedData:(id)recievedData;
@end

次に、AppClientクラスは次のようなプロパティを作成します。

@property (weak, nonatomic)id<AppClientRequestDelegate> requestDelegate;

メソッドの呼び出し元は、putToPath...AppClient のrequestDelegateプロパティのインスタンスを に設定し、メソッドを実装してから、およびパラメータselfを使用して正しい要求を検証し、パラメータを使用して何らかの処理を行います。pathsentDatareceivedData

呼び出し元のコードは次のようになります。

- (void)syncData:(id)data {
    [self.appClient putPath:@"/posts/9" withData:data];
}

- (void)appClient:(AppClient *)appClient didPutToPath:(NSString *)path withData:(id)sentData andReturnedData:(id)recievedData {
    if (/*path and sentData are right*/) {
        // Do something with recievedData
    }
}

これはすべて素晴らしいことですが、同じパスに多数の PUT リクエストがあり、プロトコルの実装内でリクエストを区別しようとする場合は最悪です。デリゲート メソッドと各リクエストの ID を指定するメソッドの両方に別のパラメーターを追加できると思いますがputToPath...、それは面倒で混乱を招きます。

もう 1 つの潜在的な懸念は、このアプリ全体で非同期読み込みを広く使用している場合です。その結果、多数のデリゲートとプロトコルが発生する可能性があります。

ブロック ソリューション

メソッド シグネチャを拡張して、ブロックを含めます。

- (void)putToPath:(NSString *)path withData:(id)data completion:(void (^)(id returnedData))completion;

確かに、この構文は非常に困難ですが、プロトコルからのすべての情報が含まれているだけでなく、メソッドの呼び出し元がすべてのロジックを 1 つのメソッドに凝縮できるため、そのメソッド内で呼び出されたローカル変数がブロックのスコープに含まれます。実装。

呼び出し元のコードは次のようになります。

- (void)syncData:(id)data {
    [self.appClient putToPath:@"/posts/9" withData:data completion:^(id returnedData) {
        // Do something with returnedData
    }];
}

結論

あなたはブロックの上手な使い方を求めましたが、これはとてもいい使い方だと思います。あなたには当てはまらないかもしれませんが、コードの量を削減するだけでなく、コードをより読みやすく堅牢にする方法を見ることができます。

于 2013-06-29T05:25:18.240 に答える