## iOS ### Themes #### iOS Design Themes **他のプラットフォームとの違い** - Clarity(明快さ - システム全体で機能にフォーカスしたデザイン - Deference(ユーザへの敬意 - ユーザの理解を助けるデザインやモーションを使いつつ,簡潔に保つ - Depth - 奥行きのあるデザインはユーザの理解を助ける - トランジションで奥行きを感じさせられる #### Design Principles - Aesthetic Integrity - アプリの見た目や振る舞いは機能に沿わせる - 特に,ユーザが重要なタスクを実行するアプリはユーザがそのタスクに集中できるように,簡素で予測可能なデザインであるべき - Consistency - 統一されたデザインを提供する - システムに提供されているものを使うことで,ユーザの期待に沿って機能を実装できる - Direct Manipulation - デバイスの動きやスクリーンへのジェスチャに対する操作を実装する(?) - Feedback - ユーザの行動に対する結果を提供する - e.g. タップされた要素のハイライト,プログレスバー - Metaphors - メタファを使う - 特に,ユーザがスクリーンに対して物理的な操作を行うiOSでは有効 - User Control - ユーザがアプリの動きを支配できていると感じられるようにする - 破壊的な操作を警告したり,要素をわかりやすく表示したり,操作をキャンセルできるようにしたりする ### Interface Essentials - iOSのアプリはUIKitを使ってデザインするのが基本 - UIKitは以下の3つのカテゴリに分けられる - Bars - アプリ内での場所の表示や移動 - その他の操作や情報のやり取りのためのボタンなどを含むことがある - Views - 主な情報を表示する - Controls - アクションを行ったり,情報を伝達したりする ## App Architecture ### Launching - アプリへの印象を決めるため重要 - デバイスや最後に起動してからの時間に関わらず,短くシームレスに行われるべき #### Provide a launch screen - 起動画面の機能は,最初のコンテンツをロードすることと,アプリが高速でレスポンシブであるという印象を与えること - 初期画面と似たようなデザインにして,起動画面自体には注目させないようにする #### Launch in the appropriate orientation - ポートレートとランドスケープのどちらもサポートするなら,デバイスの向きに応じて起動する - どちらかしかサポートしないなら常にその向きで起動し,必要ならデバイスの向きを変えるように促す #### Avoid asking for setup information up front - ユーザはアプリをすぐに使えることを期待している - デフォルトの設定は多数派に合わせる - 可能な限りデバイスの設定や既定値,iCloudなどから設定に必要な情報を取得する - もし情報を求めなければならない場合は,初回起動時に入力するように促し,その後設定画面で変更できるようにする #### Avoid showing in-app licensing agreements and disclaimers - 利用規約はアプリをダウンロードする前に表示する - アプリ内で表示しなければならない場合はユーザエクスペリエンスを損なわないように注意する #### Restore the previous state when your app restarts - 前回の状態(画面)を引き継げるようにする #### Don’t encourage rebooting - 再起動を求めると,信用できない印象を与える - メモリやその他の深刻な問題以外には(再起動以外で)対処すべき #### Avoid asking people to rate your app too quickly or too often - アプリの評価をすぐに頼んだり,頻繁に頼んだりすることは避ける - 評価を頼む表示から抜ける方法を用意し,強制してはいけない ### Onboarding アプリに慣れていないユーザの助けになる #### Provide onboarding that helps people enjoy your app, not just set it up - アプリについて学べるのはいいが,複雑で長いOnboardingは期待していない - セットアップやライセンス認証などは含めない #### Get to the action quickly - 起動画面から初期画面に切り替わったとき,すぐにアプリを使えるようにする - イントロをスキップする手段を提供する #### Anticipate the need for help - ユーザがハマりそうなところを探す - イントロを繰り返せる導線を作る #### Stick to the essentials in tutorials - ガイダンスを表示するのはいいが,それはいいデザインの変わりにはならない - アプリは常に直感的に操作できるようにすべきで,多くのガイダンスが必要になったときは設計を見直すべき #### Make learning fun and discoverable - ユーザに触らせる方が,スクショを見せたり文章を読ませたりするより効果的 ### Loading ロード中に静的なページや空のページを表示していると,フリーズと勘違いされてユーザが離脱する可能性がある #### Make it clear when loading is occurring - 最低でもスピナーを表示する - できればプログレスバー #### Show content as soon as possible - 実際のコンテンツをロード中でも,ロード中であることがわかるプレースホルダを使って画面を表示する - ロードが終わり次第コンテンツに置き換える - 可能であれば先読みする #### Educate or entertain people to mask loading time - ロード中にヒントを表示する #### Customize loading screens - 標準のインジケータでも問題ないが,必要なら自前で実装することも検討する ### Modality 一時的にコンテンツを表示して,それ以前のコンテキストと独立してユーザにアクションを求めるテクニック 以下のようなことができる - ユーザが,そのモーダル内で完結するタスク(メール等)やそれに関連したオプションに集中できる - ユーザが情報を受け取ったことを確かめられる(ユーザがアクションを起こさないとモーダルは閉じないので iOSが提供するもの - Alerts - Activity Views (or Share sheets) - Action Sheets iOS 13以降でサポートされているもの - Sheet - 画面を部分的にカバーするカード上のスタイル - 簡単なタスクに使う - Fullscreen - 画面全体をカバーするスタイル - 複雑なタスクに使う - split view paneやpopover, other view that isn’t fullscreenからモーダルを表示するときはSheetのモーダルを使うべき #### Use modality when it makes sense - モーダルはユーザが行っているタスクとは別のタスクを要求するものなので,明確な目的や利点がある状況でのみ使う #### Reserve alerts for delivering essential — and ideally actionable — information - モーダルを使ったアラートはユーザの体験を中断させるため,そのアラートによる中断がユーザにとって正当であると感じられるようにする - そう感じられない状況(それほど重要ではないアラートには)では使うべきではない #### Keep modal tasks simple, short, and narrowly focused - モーダル内で行わせるタスクは可能な限りシンプルにすべき - サブビューを含まなければいけないときは,タスクを終わらせられる必要最低限の簡潔なパスで構成する - Doneボタンはタスクを終了させる以外の目的では使わない #### Always include a button that dismisses the modal view - assistive technologies(読み上げとかそういうの)に対応できるので,DoneやCancelボタンを配置する #### When necessary, help people avoid data loss by getting confirmation before closing a modal view - ビューを閉じるとき,そのビューにあるユーザが生成したコンテンツが失われるなら,そのことと対処法をユーザに知らせる #### Don’t display a card that appears on top of a popover - アラート以外のモーダルはポップオーバーに重ねて表示してはいけない - ポップオーバー内のアクションの結果,モーダルを表示するときはポップオーバーを消してから表示する #### In general, display a title that identifies the modal task - ユーザはそれまでのコンテキストとは別のタスクを行うので,モーダルのタスクを表すタイトルを表示すると良い - モーダル内の別の箇所で詳細なガイドを表示することもできる #### Coordinate the modal view appearance with your app - モーダルの見た目はアプリの見た目に合わせる #### Choose a modal transition style that makes sense in your app - トランジションのスタイルをアプリと合わせる ### Navigation ナビゲーションは自然に,注意を惹かないような方法でできるようにする iOSでは主に3つの方式があり,複合させることもできる - Hierarchical Navigation - 構造的なナビゲーション - 選択したのとは別の画面に行くときは共通の画面まで戻ってから - ![img](/Users/taira/workspace/note/NavigationHierarchical-Graphic.png) - Flat Navigation - それぞれの画面が同一レベルにあるナビゲーション - ![Diagram that shows eight squares, with four squares in one row and the remaining four squares in a row below it. The first square in the first row connects to the second square in the first row with a double-headed arrow. In the same way, the second square connects to the third square and the third square connects to the fourth square. Each square in the first row uses a single-headed arrow to connect to the square below it in the second row.](/Users/taira/workspace/note/NavigationFlat-Graphic.png) - Content-Driven or Experience-Driven Navigation - ユーザがコンテンツ内を自由に移動できるナビゲーション - ![Diagram that shows nine circles that are connected by single-headed arrows. Some circles connect to exactly one other circle and other circles connect to more than one other circle. The diagram suggests a random path through a set of nine locations.](/Users/taira/workspace/note/NavigationExperienceDriven-Graphic.png) #### Always provide a clear path - ユーザが今どこにいてどうすれば目的の画面にたどり着けるかわかるようにする - 一般的にある画面に到達するパスは1つであるべき - そうでない状況が考えられるなら,action sheetやalertなどの使用を検討する #### Design an information structure that makes it fast and easy to get to content - それぞれの情報に最小の手数でアクセスできるように設計する #### Use touch gestures to create fluidity - 最小のタッチジェスチャで画面を移動できるようにする #### Use standard navigation components - 可能なときはいつでも標準のコンポーネントを使う - ユーザが直感的に操作できるようになる #### Use a navigation bar to traverse a hierarchy of data - ナビゲーションバーは階層構造のデータを表すのに向く #### Use a tab bar to present peer categories of content or functionality - タブバーは並列なデータやカテゴリを表すのに向く #### On iPad, use a split view instead of a tab bar - iPadではタブバーよりsplit viewを使う #### Use a page control when you have multiple pages of the same type of content - 同様なコンテンツを持つ複数ページを切り替えるときはpage controlを使う #### segmented controlsとtoolbarsはナビゲーションの機能を持たない - segmented controlsは同じ画面の別の見方を提供する(?? 多分) - toolbarsは現在のコンテンツに作用するアクションへの導線を提供する ### Requesting Permission 個人情報をアプリに提供することで便利な機能が使える利点もあるが,ユーザがコントロールできるようにする #### Request personal data only when your app clearly needs it - 本当に必要なときだけ個人情報を要求する - 必要そうでない要求は不信感を与える #### Explain why your app needs the information - 許可を求めるアラートに,例とともに目的を説明する文章を載せる #### Request permission at launch only when necessary for your app to function - 機能に必要なときだけアプリの起動時に許可を求める - 鬱陶しいが,明らかに必要な場合ユーザは気にしない #### Don’t request location information unnecessarily - Location Servicesが有効になっているかどうか調べることで,不必要にリクエストしなくて良くなる #### Use the system-provided alert - 許可を求めるときはデフォルトのアラートを使う - テキストはカスタムしてもいい ## Settings アプリが機能するのに設定が必要になる場合があるが,可能な限り遅延させ,できるなら永遠にしないほうが好ましい 多数派に合わせつつ,設定の余地は残す #### Infer what you can from the system - システムの情報からわかるときは常にシステムに問い合わせる - 郵便番号が知りたいときは,位置情報へのアクセス許可を求める - 拒否された場合は郵便番号を入力できるようにする #### Thoughtfully prioritize configuration options within your app - 頻繁に変更されうるオプションはメイン画面に置く - たまにしか変更されないオプションはセカンダリ画面に置く #### Expose infrequently changed configuration options in Settings - Settingsアプリはシステムを横断した設定を行う中心的な場所だが不便 - この画面で設定できるようにしたい場合は以下を参照 - [Implementing an iOS Settings Bundle](https://developer.apple.com/library/content/documentation/Cocoa/Conceptual/UserDefaults/Preferences/Preferences.html) #### Provide shortcuts to Settings when appropriate - Settings内の設定画面に飛ばすボタンを実装することも可能 - [openSettingsURLString](https://developer.apple.com/documentation/uikit/uiapplication/1623042-opensettingsurlstring) ## User Interaction ## 3D Touch タッチスクリーンを押してコンテキストメニューを表示できる ホームスクリーンではアプリ固有のタスクへの導線になる ### Apple Pencil and Scribble 省略 ### Audio - アプリごとに相対/絶対的に音量を調整できるが,最終的な出力はシステムの音量設定による - そうしない理由がない限りユーザが任意のデバイスをアウトプットとして選べるようにする - 音量の調整には[MPVolumeView](https://developer.apple.com/documentation/mediaplayer/mpvolumeview)を使う - 30秒以下の短い音声/バイブレーションを再生するときは[Audio Services](https://developer.apple.com/documentation/audiotoolbox/audio_services)を使う - 音を流すときは適切な [AVAudioSession.Category](https://developer.apple.com/documentation/avfaudio/avaudiosession/category)を設定する - 他の音とのミックスやバックグラウンドでの挙動などが変わる - 必要ない場合他のアプリの音を邪魔しない - 他のアプリによって中断された場合,2つのアプリのタイプを見て再開するかどうかを判断する - [shouldResume](https://developer.apple.com/documentation/avfaudio/avaudiosession/interruptionoptions/1616528-shouldresume) - Smart Folioなどの外部デバイスがオーディオセッションを中断/再開した場合の挙動を検討する - [Responding to Audio Session Interruptions](https://developer.apple.com/documentation/avfaudio/avaudiosession/responding_to_audio_session_interruptions) - 他のアプリの音を中断した場合,その中断がいつ終わるか知らせられる - [notifyOthersOnDeactivation](https://developer.apple.com/documentation/avfaudio/avaudiosession/setactiveoptions/1616603-notifyothersondeactivation) - ユーザはアプリの状態に限らず音量をコントロールできるため,それに応答できるようにする - 他のアプリがアクティブな場合は妨害してはならない - 音量のコントロールを独自に再定義してはならない - 実装しないなら単に応答しないようにする ## Authentication - ユーザに利益がある場合のみ認証する - 認証機能を実装する場合はSign in with Appleを使う - Sign in with Appleを使わない場合は[Password AutoFill](https://developer.apple.com/documentation/security/password_autofill/)を使う - サインインは可能な限り遅らせる - e.g. 商品を買う段階で求める(ショッピングアプリ),コンテンツを再生する段階で求める(動画 - サインイン画面で目的と利益を説明する - サインアップの導線も - 入力フォームにあったキーボードを表示する - passcodeというワードは使わない - 生体認証が使えるなら使ったほうがいい - 設定で無効にされている場合にも備える - 認証の方法は一つに絞る - その他の方法はフォールバックとして使う - 認証はユーザのアクションをトリガに始める - 認証方法を明記する - "Sign In with Face ID" rather than "Sign In." - デバイスの認証方法を正確に参照する - e.g. Face ID対応のデバイスでTouch IDを使わない - 生体認証の有効/無効のオプションをアプリ内で提供しない - システム全体で有効になっていたら,ユーザが生体認証を使いたがってるとみなす - システムの認証機能を表すのにアイコンを使わない ### Data Entry - 入力は退屈で面倒くさい作業なので可能な限り少なくする - テキストフィールドよりピッカーを使う - システムから取得できる情報は入力させない - 適切な初期値を入れる - 必要な値がそろってからNextやContinueボタンを有効化する - 可能な限りただちにバリデートする - 必要な値だけ入力させる - ピッカーやテーブルでは探しやすいように選択肢をソートする - 適切なプレースホルダを表示する - プレースホルダで十分なときはラベルを使わない ### Drag and Drop #### Supporting Drag and Drop - 選択可能なコンテンツはドラッグできるようにする - 編集可能なコンテンツはドロップされたコンテンツを受け入れられるようにする - 標準のエレメントはD&Dに対応している - D&Dの結果,コピーするのか移動するのかユーザが直感的に操作できるように決める - spring loading(Finderでファイルをディレクトリ上にドラッグしてきたときにディレクトリが開くあれ)の使用を検討する #### Providing Dragged Content - ドラッグされるコンテンツは高品質なものから順に複数の表現方法を提供する - e.g. PDF -> PNG -> JPEG - 可能な限りネイティブな表現でドロップ先に渡す - コンテンツのコピーや移動にリソースを食うなら[NSFileProviderExtension](https://developer.apple.com/documentation/fileprovider/nsfileproviderextension)を実装する - 進行状況を提供する #### Accepting Dropped Content - ドロップの対象となる箇所を強調するとよい - 複数ある場合は同時に一つまで - ドロップ可能な範囲の端にドラッグされたとき,コンテンツを移動させてドロップできる隙間を作るか,スクロールさせるかを選ぶ - ドロップされたコンテンツを最もリッチな表現で表示する - 可能ならドロップされたコンテンツから必要な情報だけを抜き出す - ドロップの処理に時間がかかるならプレースホルダや進行状況を表示する - ミスったときに取り消せない状況(画像の共有など)ではキャンセルできる手段を提供する ### Feedback - ユーザの行動を阻害せずに重要な情報を表示できるのが理想 - 不必要なアラートは避ける - 頻繁に不必要なアラートを鳴らした場合,ユーザが必要なアラートも無視するようになる ### File Handling - 基本的にユーザにファイルシステムを隠す設計にする - ユーザが明示的に保存しなくてもいいような設計にする - 基本的にデバイスファイルを同期できるようにする - 直感的なファイルブラウザを提供する - Quick Lookを使えるようにする - 他のアプリからファイルを開けるようにできる ### Game Controllers 省略 ### Gestures - 基本的に標準のジェスチャーを使う - ゲームなどは例外 - ショートカットジェスチャを提供する場合は既存の操作やアクションを置き換えるのではなく,補完する形にする - e.g. ナビゲーションバーにはBackボタンがあるが,画面の端からスワイプしても同じ結果になる ### Haptics - Hapticsを使う方法 - 標準のUIエレメントを使う - 規定のHapticsパターンを使う - カテゴリ(notification, impact and selection)を選ぶ - 任意のHapticsパターンを作って使う - 基本的にはシステムが提供するパターンを使ったほうがいい #### Designing with Haptics - トリガとHapticsの関係はユーザにとってわかりやすくする - 他のフィードバックを補完するように使う - ご利用は計画的に - 人の感覚には個人差があるので複数人で強さを調整する - hapticsなしでもアプリが使えるようにする ### Near Field Communication 省略 ### Pointers(iPad OS) 省略 ### Undo and Redo - 何がundo/redoされるのかアラートに書く - shakeジェスチャをundo/redoに使うなら他のアクションのトリガにしない - ボタンでundo/redoするならシステムが提供するアイコンを使う - その時点のコンテキストでのみundo/redoする ### Augmented Reality 省略 ### Notifications - 簡潔でわかりやすい文章にする - ユーザが行動を起こさないといけない通知は避ける - センシティブ/個人的な情報は通知には含まない - 通知音はあくまで補助 - プロモーショナルな通知を送るときは明示的に許可をもらう - アプリ内で通知のon/offを切り替えられるようにする - バッジはあくまで補助 - バッジを通知の数を表す目的以外で使わない ### Widgets - small, medium and largeの3種類ある - アプリを開かずにタイムリーで重要な情報を見せるのが目的 - 大きさに関わらず一貫して一つの情報を表す - 複数の大きさでwidgetを提供して価値が増えるならそうする - widgetをタップして開くページはwidgetに表示されている情報と関連したものにする - widgetの更新回数はシステムに制限されている - ロゴやフォント,色などは,widgetの情報がひと目で読める範囲で使う - widgetと似たデザインをアプリ内で使わない - widgetはホーム画面に置くもので,ホーム画面に置かれたものはアプリを開くものである - アプリ内にwidgetと似たデザインがあると,widgetと同じ動作をしないのでユーザは混乱する