オハツのカキコです☆★☆( ´ ▽ ` )ノTunnelでiOSアプリの制作を担当している富樫です。
さて、本題に移ります。RoomClipでは、投稿されている写真に対して「いいね!」したり、「フォルダに保存」したりすることができます。
それらの機能をスムーズに楽しんでもらうためには、いくつか実現しなければならないユーザ体験があるのですが、その中でもとても基本的でとても渋いものとして、「ある画面で一つの写真に対して『いいね』『保存』などを行った時に、他のスタックしている画面に戻った時にその画面でも該当写真の状態変化が反映されているようにする」というものがあります。以下はイメージ図です。
iOSではこれを実現するために、NSNotificationCenterと、UIViewControllerのpostNotificationを使って別ViewControllerにイベントの通知を行ったりもしたのですが、
- それぞれのアクションを行った後にpostNotificationする時、いちいち通知の仕様(パラメータの正確な変数名など)に気を配る必要がある
- 通知を受け取る各画面で、通知のパラメータの仕様(パラメータの変数名や型)に気を配る必要がある
ということがしんどかったので、開発メンバーに相談を行いつつ「安全に、楽に」他画面に通知を出来る仕組みを自前で作りました
通知をするために新たに作ったclass達
醜い図(mini quiz)で恐縮ですが、以下のような構成で4つのclassを準備しました。
NotificationManagerはシングルトンのクラスになっていて、アプリの中で一つだけ存在するようになっています。
NotificationManagerの中でEvent
Tは通知のために必要なパラメータの型が当てられていて、EventsオブジェクトはNotificaionの中で下記のように定義されています。
上記の例の「AddLikeParam」は、いいねをした時に他の画面に伝える必要な情報(いいねした写真のIDなど)を包括しています。
実際の実装
①
通知を受け取る必要がある画面では、NotificationManagerのなかの然るべきイベントにsubscribeする。
subscribeの引数として、通知を受け取った際の挙動を記述したblockを充てます。
ちなみに、これらの処理は全てUIViewControllerの中に記述するものとしています。
②
①を行ったUIViewControllerではsubscriptionをフィールドに保持しておき、UIViewControllerが破棄される際には、必ずsubscriptionをunsubscribeする。
Subscriptionはunsubscribeを呼び出すことにより、自身を破棄します。これを、UIViewControllerのdeallocなどで呼び出します。そうしなければUIViewControllerがリークしてしまうことがあります。
③
通知をPostする必要がある箇所で、然るべきパラメータを準備し、postを行う
これにより、①で記述したアクションが実行されます。
ちなみにviewControllerもPOSTしているのは、ある画面が送った通知を、その画面がそのまま受信するケースがあります。
そして、他画面からの通知と自分の画面からの通知とを区別してハンドリングする必要があるケースもあるからです(①のコードでvc === wselfと記述しているのがそのケースです)。
Eventsでジェネリクスを用いて安全に、迷わないように。。
さて、つらつらと書いてまいりましたが、これまで書いた中で大事だったのはEventsでジェネリクスを用いたことだと思っています。
前述の通り、Events
NotificationManagerの中で各アクションに対応するEventsオブジェクトを定義する際に「T」の型もきっちりと定義しておくことで、
- それぞれのアクションを行った後に通知をpostする時、いちいち通知の仕様(パラメータの正確な変数名など)に気を配る必要がある
- 通知を受け取る各画面で、通知のパラメータの仕様(パラメータの変数名や型)に気を配る必要がある
といった、前述したヒヤヒヤ感がなくなりました。
以上になります。長文失礼致しました。うーぬ、blogって大変ですね、また次回書く時も頑張ります。。。。

この記事を書いた人:buscemi
ルームクリップ株式会社のiOSエンジニアです。 Steve Buscemiに似てます。