ハイライト
Apple Retail は、App Groups、Swift パッケージ、XCTest、Instruments、および構成主導型 UI を使用して複数の店舗従業員用アプリを管理し、共有データ、共有コンポーネント、テストの優先順位、および地域の店舗構成をすべて同じ一連のエンジニアリング実践の下で実装できます。
主要内容
Apple Retail には 500 以上の店舗があります。従業員は毎日複数の社内アプリを使用して、予定、製品カタログ、店舗レイアウト、顧客とのコミュニケーション、営業状況を処理しています。各アプリが認証、画像キャッシュ、スキャン、モデル オブジェクト、UI コンポーネントを個別に処理すると、エンジニアリング チームは重複した実装と一貫性の修正に多くの時間を費やすことになります。
このセッションで提供されるアプローチは、「スイート」をエンジニアリング システム設計として扱うことです。複数のアプリに引き続き注目しますが、共有機能は明確な境界線に置かれます。アプリ グループはアプリ間のデータを担当し、Swift パッケージはコードの再利用を担当し、テストは異なる頻度で実行キューに優先順位付けされ、運用環境の違いは構成ファイルとサーバー側のスイッチによって決まります。
このアプローチは、単一のフレームワークに焦点を当てていません。これには、エンタープライズ アプリに関する 4 つの長期的な課題がまとめられています。それは、複数のアプリ間でアプリを共有する方法、パブリック コードを作成する方法、リリース前に検証する方法、リリース後にさまざまな地域、市場、ストアに適応する方法です。エンタープライズ チームにとって、これは巨大な単一アプリを構築するよりも保守が容易であり、複数のビジネス チームを並行して進化させるのにより適しています。
講義中のスキャン例も代表的なものです。 Apple Retail が Vision と AVFoundation を社内でラップRetailScannerパッケージは、統合された構成オブジェクト、デフォルトの UI、およびビジネス アプリへのデリゲート コールバックを公開します。ビジネス エンジニアは、さまざまなアプリで一貫したスキャン エクスペリエンスを得るために、カメラ、バーコード、OCR、およびアクセシビリティ機能の詳細を繰り返し理解する必要はありません。
最後に、実稼働構成により、ビジネスの変更がクライアントのリリースから分離されます。顧客フォームの電子メールまたは電話番号フィールドをオフラインにする場合、チームはサーバー上でホストされている構成ファイルを変更します。次回アプリを起動すると、新しい構成が読み取られ、UI を更新できます。このメカニズムにより、一時的なリリースが減りますが、クライアント、サーバー、および構成のバージョンの互換性が維持される必要もあります。
詳細
アプリ グループ: まず、アプリ間でのデータ共有の問題を解決します。
(01:23) Apple Retail によって採用された最初の iOS 機能の 1 つは、App Groups です。有効にすると、同じ開発者ポータル内の複数のアプリを共有コンテナを通じて交換できるようになります。UserDefaultsそして書類。 Xcode への入り口は署名と機能にあります。アプリ グループ機能を追加して、グループを作成します。
(01:57) 講演で示されたコードは以下から共有されています。UserDefaults始める:
let sharedDefaults = UserDefaults(suiteName: "group.com.apple.myappgroup")!
sharedDefaults.set("My Cool Value", forKey: "MyKeyName")
let myKeyNameValue = sharedDefaults.string(forKey: "MyKeyName")
キーポイント:
suiteNameアプリ グループ識別子を使用すると、同じグループに参加するアプリのみがこのデフォルトにアクセスできます。 -set(_:forKey:)軽量の構成とステータスに適した共有キーの値を書き込みます。 -string(forKey:)同じ共有ドメイン内の値を読み取ると、同じグループ内の他のアプリも同じキーに基づいて値を取得できます。- トランスクリプトには共有ファイルについても言及されており、キー値よりも大きい共有データに適しています。
Swift パッケージ: 再現性を安定した境界に収束させる
(02:23) このプレゼンテーションにおける Swift パッケージの役割は、重複コードを減らし、人的エラーを減らし、エンジニアがチーム間を移動するときに既存のコードを理解しやすくすることです。 Apple Retail は、これらのコンポーネントに長期所有者が付くように、パッケージの保守を専門に行うチームも設立しました。
(02:57) スピーチにリストされている候補者の能力は非常に具体的です。URLSession認証パッケージ、イメージ キャプチャおよびディスク キャッシュ パッケージ、UIKit のカスタム テーブル ビュー セルと製品詳細ビュー、顧客/予定/製品およびその他のモデル オブジェクト、およびスキャン パッケージ。これらの機能には共通点が 1 つあります。それは、複数のアプリで使用する必要があり、その動作が一貫している必要があることです。
(05:03) スキャン パッケージのバーコードの例は、統合された構成オブジェクトとビュー コントローラーの初期化モードを示しています。こちらですRetailScannerこれは Apple Retail の内部パッケージであり、パッケージ化方法を記述するために使用され、公開システム フレームワークではありません。
import RetailScanner
let scanOptions = BarcodeScanOptions()
scanOptions.scanRegion = .regular
scanOptions.shouldAddSupplementaryView = false
scanOptions.shouldShowBarcodeDetector = true
let barcodeViewController = BarcodeScannerViewController(scanOptions: scanOptions)
barcodeViewController.delegate = self
キーポイント:
BarcodeScanOptionsスキャン領域、補助ビュー、検出器の表示設定を一元的に保存します。 -BarcodeScannerViewController(scanOptions:)構成を初期化パラメーターとして使用すると、複数のアプリで同じ構成セットを再利用しやすくなります。 -delegateスキャンの成功と失敗のメッセージを受け取ると、ビジネス アプリはカメラと認識のプロセスを繰り返さずに結果のみを処理します。
(05:23) OCR の例は、同じ構成と初期化パターンに従います。
import RetailScanner
let scanOptions = OCRScanOptions(
scanRegion: .custom(CGSize(width: 400, height: 100)),
accessibilityBehavior: .vibrate,
shouldAddSupplementaryView: true,
validation: nil,
shouldShowResultView: true
)
scanOptions.recognitionLevel = .fast
let ocrViewController = OCRScannerViewController(
scanOptions: scanOptions
)
ocrViewController.delegate = self
キーポイント:
scanRegion無関係な画面の干渉を減らすために、OCR 認識範囲をカスタム サイズに制限します。 -accessibilityBehaviorスキャンのフィードバックでアクセシビリティのニーズに対応しましょう。講演では、スキャン パッケージがカスタマイズされたアクセシビリティ サポートをサポートしていると述べられました。 -recognitionLevel = .fastリアルタイム OCR シナリオに対応し、スキャン プロセス中のフィードバック速度の確保が優先されます。- バーコードと OCR は同じ設計モデルを使用するため、ビジネス エンジニアは機能を切り替えるときに一連の API を再学習する必要がありません。
テスト: 手動回帰を実行可能なエンジニアリング プロセスに分割する
(05:48) アプリが完成した後、Apple Retail は多くの手動テストに依存しませんでした。講演では、テストを単体テスト、UI テスト、パフォーマンス テストに分けました。単体テストは、各コード パスの予想される戻り値をカバーすることを目的として、クラスや関数を作成するときにエンジニアリング チームによって完了します。
(06:40) UI テストでは、XCUITest を使用して、QE チームの既存の手動テスト ケースを Swift にコーディングします。 UI テストは実行に時間がかかり、最も重要なテストはより頻繁に実行する必要があるため、テストの作成後は重要度に応じて分割されます。
check-in: run the most important UI tests
daily: run a broader set of regression tests
weekly: run lower-priority or longer tests
キーポイント:
check-inレベル テストは、高リスクの回帰をできるだけ早くブロックする責任があります。dailyテストにより対象範囲が拡大され、コア パスの外側のシナリオに適しています。 -weeklyテストでは、より長く優先度の低い回帰コンテンツがホストされます。- 優先度によるスケジュール設定により、重大な障害の発見時間を短縮できます。
(07:21) パフォーマンス テストは、レンダリング パフォーマンスとバッテリー パフォーマンスの 2 つのことに焦点を当てています。店舗の機器は店内で一日中使用されており、従業員が機器を充電するために持っていくと生産性が低下します。したがって、バッテリーのパフォーマンスは、スクロールやドラッグなどの操作のスムーズさと同じくらい重要です。
Instruments
→ rendering performance
→ memory usage
→ battery usage
→ long-running operations
キーポイント:
Instrumentsこれは Xcode の組み込みツールであり、実行時間、メモリ、電力の異常を分析するために音声で使用されます。 -rendering performanceリストのスクロールやドラッグなどの高頻度のインタラクションに対応します。 -battery usage機器が店舗から離れると従業員の仕事に影響を与えるため、企業の店舗シナリオではこれは非常に重要です。- これらの指標は、従業員が 1 日を通して使用するものに近づけるために、実際のデバイスで観察する必要があります。
構成主導の UI: クライアント リリースに本番環境の差異を含めない
(08:41) 運用管理部分では、クライアント ベースの構成ファイルとサーバー ベースの構成という 2 種類の構成について説明します。前者はクライアント内にマッピングがありますが、構成ファイルはサーバー上でホストされます。後者はサーバーからダウンロードされたブール値で、アプリの動作を制御するために使用されます。
(09:10) クライアント構成は、UI 要素の制御に適しています。 Apple Retail は、コードを変更したり、クライアント ビルドを再送信したりすることなく、地域、市場、店舗レベルごとにエクスペリエンスを調整できます。
PLIST attributes in client code
→ hosted as JSON on the server
→ app downloads attributes during startup
→ UI renders only the configured fields
キーポイント:
PLIST attributesクライアントに既知のフィールド定義です。 -hosted as JSON設定コンテンツがサーバーから配布されることを示します。 -startup構成を段階的にダウンロードして、アプリを開いたときに最新のフィールドが使用されるようにします。- UI は設定どおりに表示されるため、ビジネス チームは店舗レベルまたは市場レベルの違いを迅速に調整できます。
(12:10) 顧客フォームの例は、構成主導型 UI が該当する部分を示しています。公式コード スニペットには、2 種類のセルの構成エントリのみが示されています。
func configuredCellForLabel(for customerInfoField: CustomerInfoField, at indexPath: IndexPath) -> UITableViewCell { ... }
func configuredCellForPhoneNumber(for customerInfoField: CustomerInfoField, at indexPath: IndexPath) -> UITableViewCell { ... }
キーポイント:
CustomerInfoFieldフォーム フィールドをユニバーサル入力に抽象化し、どのフィールドを表示するかを簡単に設定できるようにします。 -configuredCellForLabel名、姓、電子メールなどの通常のテキスト フィールドを処理します。 -configuredCellForPhoneNumber電話番号など、特別な入力動作が必要なフィールドを処理します。- 設定ファイルから電子メールまたは電話番号を削除すると、次回アプリを起動した後、対応するセルは表示されなくなります。
(13:42) ドライバーの構成には互換性管理のコストがかかります。新しいサーバー構成は古いクライアントによって認識されない可能性があり、新しいクライアント属性にはまだサーバー マッピングが存在しない可能性があります。 Apple Retail は、構成バージョン管理を使用して、ダウンロードされたクライアント/サーバー構成バージョンを特定し、表示するエクスペリエンスを決定します。両者が相互にサポートできない場合、ユーザーはアプリを更新する必要があります。
重要ポイント
-
対処方法: 認証とネットワーク アクセスを共有パッケージに組み込みます。なぜそれを行う価値があるのか: トランスクリプトには、Apple Retail が認証を組み込んでいることが明確に述べられています。
URLSession上記のように、ビジネス エンジニアは認定資格の詳細を繰り返し扱う必要はありません。開始方法: まずリクエスト構造、トークン更新、エラー処理を抽出してから、各ビジネス アプリが同じ Swift パッケージに依存できるようにします。 -
やるべきこと: バーコードと OCR 用の統合スキャン ポータルを構築します。実行する価値がある理由: スキャン機能には、Vision、AVFoundation、デフォルト UI、アクセシビリティ フィードバック、およびデリゲート コールバックが必要です。実装を繰り返すと、経験に違いが生じやすくなります。開始方法: スピーチに従ってください
BarcodeScanOptions、OCRScanOptionsコントローラーの初期化モードを表示し、最初に最も一般的に使用されるスキャン プロセスをパッケージ化します。 -
対処方法: エンタープライズ アプリの UI テストを階層順に実行します。実行する価値がある理由: プレゼンテーションを毎日、毎週チェックインすることで、回帰を完全にカバーしながら、重大な障害を早期に発見できます。開始方法: 既存の手動ユース ケースを XCUITest に変換し、各ユース ケースに優先順位と実行頻度をマークします。
-
対処方法: ストアまたはリージョンの違いを構成ドライバー フォームに入力します。実行する価値がある理由: 顧客フォームの例は、フィールドの削除が構成を通じて実行でき、新しいクライアントのビルドが必要ないことを示しています。開始方法: まずフォームフィールドを抽象化します。
CustomerInfoFieldを選択し、起動プロセスでサーバー上でホストされている JSON 構成をダウンロードします。 -
対処方法: バージョンの互換性と強制更新ルールを構成システムに追加します。実行する価値がある理由: このセッションでは、サーバーとクライアントの構成が相互にサポートしていない可能性があることが明確に指摘されています。バージョンを判断できないため、古いクライアントは理解できない新しい構成を取得できます。開始方法: クライアント構成とサーバー構成のバージョンを個別に記録し、開始時に互換性マトリックスを確認してから、新しいエクスペリエンスを有効にするか、更新を求めるプロンプトを決定するかを決定します。
関連セッション
- 従業員向けのカスタム アプリを作成する — 従業員の問題点に基づいてエンタープライズ アプリを設計する方法について話すのは、このセッションの製品化前のコンテンツです。
- エンタープライズ ID と認証の活用 — エンタープライズ ID、SSO 拡張機能、およびアプリ スイートでのログインと資格情報の管理を完了できる管理対象 Apple ID について説明します。
- Apple Business Manager を使用したカスタム アプリの配布 — キット開発の完了後のカスタム エンタープライズ アプリの作成と配布のプロセスについて説明します。
- バイナリ フレームワークを Swift パッケージとして配布する — 共有コンポーネントのパッケージ配信方法を補うためにバイナリ フレームワークを配布する Swift パッケージについて説明します。
- テスト結果をより速く取得する - Xcode テスト計画、xcodebuild、および XCTest のタイムアウト メカニズムについて説明し、このセッションのテスト スケーラビリティのトピックを拡張します。
コメント
GitHub Issues · utterances