iOS のポップアップUIのクローンライブラリを作りました
iOSのApp Storeアプリでレビューをした後、ポップアップ表示が出ますが、それが良い感じなのでクローンライブラリを作りました(UIKitには含まれてないので)。
標準のポップアップUIは今のところApp Storeにて👍・👎のアイコンとセットで表示されるだけですが、NativePopupでは好きな画像・絵文字にも対応したので、けっこう便利に汎用的に使えるかと思います💁
ポップアップUIの特徴
- 何かの操作直後に、下からひゅいっと出てきて真ん中に1.5秒程度表示され、その後自然にフェードアウト
- 表示中にポップアップをタップなどしても何も反応しない
- 逆に、ポップアップの背面への操作などもブロックしない
AndroidのToast と少し似ていますが、Toastは画面端にさりげなく表示されることに比べてiOS ポップアップUIは必ず視認される真ん中に表示される、という部分が大きく異なるかなと思っています。
iOS標準アプリでToastぽい表示が無いのは、Toast出しても気付かれ無いことがあったり気付いて読もうと思ったら消えてしまったりで、それならば表示せずで良いのでは?と判断しているのかなと想像しています。逆に表示する以上ある程度目立つようにするべきで、さりげない表示は中途半端になりがちなのかなと。
ポップアップUIはどういう場面で使う?
iOSでも10.3までは標準アプリでポップアップUIの出番は無く、また10.3でもApp Storeでレビューに対してフィードバックした後の表示に使われているのみということで、それだけ見ると利用箇所は限定的かな?とも思えます。
iOS標準アプリでは、ユーザー操作を邪魔しないように、特に大事な時のみアラートビュー・アクションシートを表示するようになっています(iOSヒューマンインターフェイスガイドライン: 一時ビューに詳しく書いてあったのですが、今見たら消えて英語の別ページにリダイレクトされるようになってました…)。
iOS標準アプリでは、それ以外のカジュアルな操作のフィードバックは、明らかな場合は何も表示せず、あるいは何もフィードバックが無いと分かりにくいケースではちょっと凝った表示がなされます(下はSafariの例)。
あるいは何もフィードバックが無いと分かりにくいケースではちょっと凝った表示がなされます
これが理想ではありますが、デザイン・実装には手間のかかることも多いため、この代わりにポップアップ表示して省力化、というのがメインの利用シーンなのではと個人的には解釈しています。
常にすべての画面を全力で組めるほど、開発リソースに余裕の無いことが多いですし、とりあえず良い感じにデザインされたポップアップUIを表示するようにしておいて、あとで余裕の出てきたタイミングで凝ったUIに改善、というフローなどしっくり来ます( ´・‿・`)
NativePopupを作っていて思ったこと
オリジナルデザイン通りに組む作業が多少面倒(サイズ測ったり実寸あわせしたり)だとは予想しつつ、他は何も考えずにできるレベルかなー、などと思っていましたが、意外と学ぶことも多かったです。
Embedded Framework でのxcassetsの画像の取り扱い
以下の記事で書いたとおり、Embedded Frameworkは多用していますが、UIの絡むものはあまり使ったことが無かったので、xcassetsの画像参照については、少し戸惑いました。
UIImageは通常init(named:)
というイニシャライザーで初期化しますが、Embedded Frameworkを使っている場合、これでは画像が見つからず実行時エラーになってしまいます。
代わりにinit(named:in:compatibleWith:)を用いて、Embedded Frameworkのbundleを明示するとうまく画像を参照することができます。iOS 8以上で使えるイニシャライザーで、Embedded FrameworkもiOS 8以上なので、なるほどと思いました( ´・‿・`)
let image = UIImage(named: "name", in: Bundle(for: NativePopup.self), compatibleWith: nil)!
ライブラリ・Xib不使用で、コードのAutoLayoutのみで組んでみた
コードのみで組む派をたまに見かけるので、トライしてみました。iOS 9からはライブラリ使わずともAutoLayoutをコードで書きやすくなっていて、これはありだなと思いました。ベタ書きだと若干冗長になるので、随時薄いラッパーメソッド用意するのが良いかなとも思いましたが。
ただ、 NSLayoutAnchor
に対しては大きな不満点もあり、 .isActive = true
を書く必要があるということです。戻り値不使用の警告表示するか、あるいはデフォルトtrueであれば良いなと思います。この書き忘れで、何回かハマりました。
コードだけでレイアウト組むのはまあまあありかなとも思いつつ、制約に矛盾があるかどうか随時表示されるStoryboard・Xibの方が個人的にはやりやすいかなと思いました。一長一短だと思います。
Extensionをモダンでオシャレに
以下の記事が良いなと思っていて、そのまま真似させていただきました🙇公開ライブラリの場合は、こういう部分も丁寧にやった方が良いなと思いました。
Convertibleパターン
以下の記事でおまけ程度に触れましたが、image引数にはAlamofireなどでも取り入れられているConvertibleパターンを用いました。このおかげで、Usage の通り利用者側に優しいインターフェースとなっていて、さらにライブラリ側としてもいくつもオーバーロード用意せずに済むのも良いです。
Convertibleパターンは、1本の別記事として近々書きたいなと思っています🤔