2

私は平均的な iOS 開発者です。頻繁に使用されている最初のデザイン パターンは、主にコールバック機能に使用されていた Delegation パターンでした。

ブロックがObjective Cにあり、ブロックを頻繁に使用してデリゲートを回避するライブラリがますます増えているので、ブロックはプロトコルを使用したデリゲートパターンの恒久的な代替品ですか?

私は最近、プロジェクトで MKNetworkKit を使用しました。その上にラッパー クラスを作成しました。ライブラリはブロック ベースであるため、ブロック ベースのコードの 1 つへの呼び出しをカプセル化するすべてのコードは、別のブロック ベースのコードになりました。

最初は非常に便利でしたが、コードが複雑に見えたため、デバッグと変更が困難でした (コールバック内のコールバック内のコールバック!)。

いつ何を使用するか、特定のベスト プラクティスに関するヒントはありますか?

4

2 に答える 2

4

デリゲートとブロックはどちらも、結果を「コールバック」するために使用されます。通常は、結果を作成したものに使用されます。いくつかの違いがあります:

  • デリゲート プロトコルを使用すると、コールバックを受け取るために実装する必要があるメソッド名が固定されます。つまり、同じデリゲート プロトコルを使用して複数の可能なアクションからコールバックを受信する必要がある場合は、何らかの方法でそれらを区別する必要があります。ブロックには決まった名前はありません。特定のシグネチャを持つブロック オブジェクトを渡すだけです。さまざまなブロック オブジェクトをさまざまなアクションに渡すことができます。
  • デリゲート プロトコルには、多くの場合 (常にではありません)、「成功」と「失敗」のコールバックなど、複数のコールバック メソッドが含まれます。各ブロックは 1 つのコールバックとしてのみ機能します。多くのライブラリは、複数の引数を使用して、複数のデリゲート コールバックを単一のブロック コールバックに「結合」しようとします。たとえば、ブロックには 2 つの引数 (結果、エラー) があり、「エラー」が nil の場合、元の「成功」コールバックに対応します。 「結果」はデータです。「エラー」が nil でない場合は、元の「失敗」コールバックに対応します。もう 1 つのオプションは、アクションに複数のブロックを別々に与えることです (たとえば、「成功ブロック」プロパティと「失敗ブロック」プロパティを設定できます)。これはより一般的で、
  • メモリ管理: デリゲートは通常、デリゲートを所有する「親」オブジェクトであるため、通常、デリゲートは弱参照されます。ただし、ブロックは委任者に渡されると不要になる 1 回限りのものであるため、ブロックは強く参照されます。とはいえ、よく考えてみれば全然違いますね。デリゲートでは、通常、デリゲート メソッドはそれ自体 (親オブジェクト) に対して何らかのアクションを実行します。ブロックでは、これを行うために、ブロックは「親」への参照を必要とします。デリゲート パターンのメモリ管理をエミュレートするために、弱参照にする必要があるのはこの参照です。ブロックを使用すると、親オブジェクト コードはブロックを設定するため、デリゲートがそれを参照する方法をより詳細に制御できます。

結論として、デリゲート プロトコルを使用する API をブロックを使用する API に体系的に変換することは可能です。これには、デリゲート メソッドごとに、デリゲート メソッドに 1 つのブロック プロパティを追加します。

于 2012-12-08T10:58:35.920 に答える
0

プロトコルと、それらが対話する指定されたデリゲート オブジェクトは、通常、タスクをカプセル化したり、GCD に送信したりするために使用される ブロックベースのコードとはまったく異なります。

デリゲートが提供する機能の一部と一致するように見える Apple のブロック ドキュメントの 1 つの場所を確認します。

ブロックは、コールバックで実行されるコードとその実行中に必要なデータの両方を運ぶため、コールバックとして特に役立ちます。

于 2012-12-08T05:53:43.657 に答える