今日は再びひとつ前の脱線に戻って、iOS 系のチップス集といえそうなブログ 同じような処理だけどこっちの方がいいよってやつ の続きから眺めていきますね。テーマとしては アイコン
のところから。せっかくの Swift 勉強会なので、何か思い当たれば Swift 言語仕様の観点からも注目しつつ、いつもよりアプリ作りに近いあたりを見ていきましょう。よろしくお願いしますね。
—————————————————————————————————— 熊谷さんのやさしい Swift 勉強会 #296
00:00 開始 00:44 Swift 言語仕様の話もけっこう即効性のある実用的話題 02:44 実用の話題を言語仕様の観点から眺めていくのも楽しい 03:25 アイコンを SF Symbols で表現していく 07:34 断言することで説得力が上がる? 10:04 SF Symbols と Voice Over 11:38 アクセシビリティー対応 16:32 Voice Over のテストは難しい 19:44 アクセシビリティーの自動検査 20:19 Swift らしいエラー告知のしかた 28:09 ここで @nonobjc を明記しているのが気になる 29:26 クロージング ——————————————————————————————————
Transcription & Summarize : 熊谷さんのやさしい Swift 勉強会 #296
はい、それでは始めていきましょう。今日は久しぶりに少し寄り道して、Safariのエクステンションなどを作っていましたが、また元のトピックに戻りましょう。今日は、ブログ「のっぺいさんの同じような処理だけど、こっちのほうがいいよ」について話していきます。このブログは、特にiOS周りに限定した内容ではないですが、そういった方面のチップス集として役立つものです。
Swiftも意外と実用的ですし、この勉強会を通して、その点を再認識しています。やっぱり言語仕様というのは、何気ない部分に難しさや奥深さがありますし、些細な動きが実用面では非常に大事になってきます。そのため、このような勉強会は、週に3回、言語仕様に触れるいい機会だと思います。実際、非常に多くを学んでおり、話しながら自分でも勉強になっていると感じます。
さて、本題に戻りましょう。今日は「アイコン」というところから始めます。ここではシンプルな表現がクイズ的に出てきます。例えば、あるコードを見て次にどう改善すればよいかを考えるという内容です。このブログのテーマは「同じ処理でも、こちらの書き方のほうが良い」というものです。より良い書き方についてのアドバイスが続々と出てくるので、それを見ていきましょう。
例えば、次のようなコードがあります:
let image = UIImage(named: "my_image")
このコードでは文字列リテラルを使用しているため、打ち間違えたときにいろいろと厄介なことが起きます。したがって、なるべくテキストのフリーなテキストよりも、ドットを打つと候補が出てくるようなコード補完を利用するのが主流になっています。
次も同じようなテーマで進めていきましょう。これは同じような処理の改良版を見ていくブログ内容なので、きっとここも改善されているはずです。例えば:
let imageName = "my_image"
このような形で、コードをより安全で誤りにくい形にするような工夫が施されています。
今日の話題はここで終了しますが、次回も引き続き別の改善案について探っていきましょう。ありがとうぞざいました。 次に説明に入りますが、次はSF Symbolsについてです。iOSアプリを作っていたときにSF Symbolsを使っていなかったので、あまり馴染みがありませんでしたが、あれは便利ですよね。システム画像として利用することができますから。特に、iOSアプリを作成している人たちにとってはお馴染みのツールでしょう。
SF Symbolsは、統一感のあるアイコンセットを提供してくれます。昔のアプリでは、ユーザーが「このマークを押すと何が起きるんだろう?」と思うことが多かったですが、最近では統一感が持たせられています。特にmacOSでは、マウスを乗せるとポップアップが出てきますが、iPhoneの場合はタッチするまで分からないこともあります。そのため、アプリのアイコンに何か書かれていると、「これは何が起こるのだろう?」と思ってしまうことが多いです。しかし、アイコンが統一されていれば、ユーザーも慣れやすくなりますし、公式が提供しているものを使えば、既に広まったイメージをそのまま利用できるのが利点です。
SF Symbolsを極力使うべきだという意見もありますね。こうした技術的な意見は参考になります。技術ブログなどで自信をもって情報を発信することが重要だとよく言われますが、自分は自信がないことでも率直に言ってくれる方が信用できると感じます。
一部の意見に「SF Symbolsを無視する理由はない」という話がありましたが、実際に使わないといった理由は、慣れていないからかもしれません。特に、目の不自由な人に優しいアプリを作る上でボイスオーバー対応が既にされているというのは非常に大きな利点ですね。
独自のUIを作るときに、ボイスオーバーへの対応が不足していることがあります。そのため、見た目の改善程度なら標準のUIに寄せた方が良いという場合もあります。SF Symbolsを使えば、ボイスオーバー対応が既に含まれているので安心です。例えば、システム画像を使ってボタンを設置すると、そのボタンにもボイスオーバーが反応し、適切に読み上げてくれます。
アクセシビリティに関する設定は、UIのヒントなどを設定すればいいのかもしれません。これはドキュメントを探す必要があるかも知れませんが、自分は行き当たりばったりが好きで、ドキュメントを読む癖がなかったため、その存在を気にしていませんでした。結局、行き当たりばったりで様々なことを学んだところも多いので、同じような道を辿るのが好きなんですよね。 UIViewの中にアクセシビリティのオプションがいろいろとありますよね。たとえば、ヒントなどがあります。そのため、UIImageにもアクセシビリティ機能が含まれているはずです。こういった機能が整備されていると、自動で処理できる可能性が高まりますね。素晴らしいですね。
アクセシビリティが標準搭載されていることで、間違った使い方を抑制する効果も期待できます。こういったレールを敷くことは大事です。たとえば、SF Symbolsやその他のソフトウェアアニメーションなどでアニメーションを設定することができます。全体を表現しなくても、ある特定のアニメーションだけでも問題ありません。重要なのは、使う人に正しく伝わることです。
ボイスオーバーなどの機能については、自分は使っていないので急にはできる自信がありませんが、それでも一度試してみる価値はあるかもしれません。UIを作っている人なら、ボイスオーバーのテストもしているはずです。アプリを作ったときに、ボイスオーバー的に正しいかどうかをチェックすることも重要です。しかし、これはコストがかかる作業です。最低限でも使えるようにするのが現実的かもしれません。
アクセシビリティの設定は翻訳と似たような感じかもしれません。ボタンに適切な説明文があっても、日本語としては違和感がないけれど、実際の操作ではわかりにくいことがあります。特にシステムに自動で設定されない部分は、自分で設定しなければなりません。
たとえば、ボタンが実際にボタンとして機能するかどうかを効果的に伝えるためには、呼び出し方やボタンとして読み上げられるようにすることが重要です。そのためには、開発者がきちんと設定する必要があります。もちろん、ユーザーの視点から見て使いやすさを確認することが大切です。
特に、目の不自由な人向けのアプリを開発する場合は、実際に不自由な人にテストしてもらうことが必要です。そういったケースではしっかりとしたテストが求められますが、それに伴うコストも考慮する必要があります。たとえば、公共交通機関のアプリなどは、視覚障害者が使えることが重要です。
以上のように、アクセシビリティを考える際にはさまざまな視点での工夫が必要であり、そのためのツールや機能をどのように活用するかが鍵となります。 最初期のアクセシビリティのラベルや複雑な自動検出が搭載されているんですね。こういった機能があると、テストも多くなります。いわゆるテストですが、最低限ここだけは満たそうというラインがあるといいですね。
インターフェースも興味深いものがあります。特に、ベータ版として搭載される機能が興味深いです。こうしてどんどんアクセシビリティに寄せていくのは素晴らしいことです。
次に話を進めますが、少し興味深い用語が出てきました。パソコンアクセシビリティのオーディットについて話しましたが、この単語について具体的に分かっていませんでした。そこで調べてみたところ、信頼度などを検査することを指しているようです。おそらく直ぐに忘れてしまうかもしれませんが、覚えておかないといけないですね。
また、エラーハンドリングについても議論しました。返す状況を細かく使えるためのエラーハンドリングは面白いアプローチです。エラーハンドリングは、昔のC++の頃から重たいイメージがあったので、新しいやり方が軽快に感じます。
例えば、「正常の戻り値がリターンで、エラーの戻り値がスロー」といったような軽い感じのエラーハンドリングが一般的です。そのための良い例も出てきました。しかし、ブール値を返すか、細かいメッセージを返すかで迷うことが多いです。言語的な流儀として、エラーメッセージとエラーナンバーを変数に入れる方法もありますし、正常時にはnil
を返してエラー時にはエラーメッセージを返す方法もあります。
例えばnil
が返される場合はエラーがなかったことを意味します。あるいは、タプルを使って正常か異常かを判定し、異常だった場合にはエラーメッセージを返すことも考えられます。しかし、条件判定が複雑になりがちで、正常時にエラーメッセージが返ってくるミスも発生しやすいです。
最後に、コールバックを使った手法もあります。正常な答えとエラーが両方オプショナルで返ってくる場合、どのようにエラーハンドリングすべきか迷うことがよくあります。こうしたケースでも、適切なエラーハンドリングの方法を模索する必要がありますね。 エラーハンドラーにおいて、エラーのときや正常のときのバリューとエラーをどう扱うかについて話していました。エラーが発生したときに if let error
で判定する方法は正しいのか、また正常な値が返ってきたときにどのように処理するかは、考え方によって結論が異なります。
具体的には、値とエラーの両方が取得できた場合、どちらが正常でどちらが異常かを判断します。たとえば、ケースによっては片方のバリューが取り出せて片方が nil
だったら正常系の処理を行います。一方、片方が nil
でもう片方がエラーだった場合、それは異常系の処理となります。それ以外であれば、値が両方とも存在する場合や、両方が nil
の場合は、致命的なエラーとして扱います。
また、エラーハンドリングをどう書くべきか、これは悩む点です。エラーハンドリングでは、エラーがあった場合の詳細を返すことが重要です。適切か異常かを明確にするために、エラーハンドリングをきちんと書いておくことは必要ですね。
さらに、興味深い点として、@objc
(オブジェクティブC)互換性についての話がありました。特に、@objc
を付けるか付けないか、付けるとオブジェクティブCのAPIでもスウィートAPIでも使用可能になる点について考察していました。もし、オブジェクティブCランタイム互換にしたほうが良い場合は、@objc
を付ける必要があります。特にストラクトがオブジェクティブC互換になっていない場合は、付けることで問題が解決します。
最後に、ブール値を返しているエラーハンドリングの話も出ましたが、これは珍しいパターンであり、エラーハンドリングと意味合いが異なる場合でも両立できる可能性があるという点で興味深かったです。
これで今日は終わりにしましょう。次回は今日触れられなかった部分について、もう少し詳しく話すかもしれません。お疲れさまでした。ありがとうございました。