web-dev-qa-db-ja.com

いつ、どこで、コールバックを行う方法

最近、Swiftを使用してiOSでネットワーク関連の作業を行う、より複雑なプログラミングを開始しました。これにより、ネットワーキングだけでなく、View Controller間の情報交換にも多くの非同期コードが導入されました。

とにかく、私の質問は単純で、非常に一般的です。私が知る限り、コールバックを行う方法は(少なくとも)4つあります。そのため、どちらの場合もどちらが良いかという一般的なルールはありますか?

  • 関数の引数としてのコールバッククロージャ(関数)
  • プロトコルによる委任
  • 通知(またはオブザーバー)
  • 共有状態オブジェクト

アプリケーションのユースケース

  • ネットワーク関連、POSTリクエストまたはファイルのダウンロード
  • ボタンタップ時にビューコントローラー間で一方向にデータを渡す
  • ビューコントローラー間で双方向にデータを渡す(1つのビューには選択したオプションが表示され、別のビューにはユーザーが選択する実際のオプションが表示されます)
4
Shane Hsu

さまざまな観測パターンに対する私の見解を以下に示します。コメントに必要と思われる場合は、このリストを随時更新する可能性があります。

  1. クロージャー付きのコールバック:これは、ある種のワンショット(ネットワーク応答など)、またはすべてを同じ方法で処理する必要がある複数の応答がある場合に最適です。異なる方法で処理する必要のある複数の応答や、異なる種類の応答が必要な場合(応答の種類ごとに異なるクロージャーが必要になる場合)は、あまり良くありません。応答に関心のある複数のオブジェクトがある場合も役に立ちません。
  2. プロトコルを使用した委任:リスナー/オブザーバーが1つだけでなければならないというビジネス上の理由があり、そのオブザーバーがいくつかの異なる状態変化を処理することが理にかなっている場合、多くの意味があります。つまり、件名に関心のあるオブジェクトが複数ある場合、委任は機能しません。 1つのメソッドの実装のみを強制するプロトコルになってしまう場合は、このパターンもおそらく良い考えではありません。また、問題のプロトコルを実装するいくつかの異なるオブジェクトを追跡するオブザーバーがいる場合は、このパターンの使用を再考する必要があります。
  3. Notification:NSNotificationCenterは、非常に一般的なメッセージまたはシステム全体のメッセージに対して非常にうまく機能します。オブザーバーが1人だけの場合、またはメッセージが1回だけ送信されることを期待している場合、これはパターンの選択としては適切ではありません。また、このパターンを使用すると、成熟したシステム内の2つの異なるオブジェクト間でメッセージを送信する必要がある場合(つまり、ハッキングなど)のリファクタリングを大幅に節約できます。
  4. Key value Observation:これは、オブザーバーが単一のフィールドの状態のみを監視する必要がある場合にうまく機能しますが、複数のフィールドを監視しようとする場合や、いくつかの信号を通知するだけの場合は扱いにくくなります。

あなたが言及しなかったいくつかのパターン:

  1. target/action callback:これの例はUIControlです...これには、クロージャー付きのコールバックと同じ利点とトレードオフがあり、大部分はそれで置き換えられたと思います。
  2. 抽象メソッド/サブクラスのインスタンス化:サブクラスにメソッドを実装して基本クラスの要件を処理するクラシックモードがあります。 UIViewControllerのviewDidLoadなどが例です。プロトコルによって主に取って代わられたもう1つのパターンですが、すでにクラス構造が配置されている場合に便利です。
  3. Futures/Promises:このパターンには、コールバッククロージャと同じ利点と欠点がありますが、ポップアップするネストされたクロージャを回避できます。

最後に、上記のすべてのパターンに取って代わることができるreactive programming(たとえば、ReactiveCocoaおよびRxSwift)があります。学ぶには少し時間がかかりますが、こつをつかめば、1つのパターンですべての観察ニーズに対応できます。

1
Daniel T.