WWDC Quick Look 💓 By SwiftGGTeam
Use the camera for keyboard input in your app

Use the camera for keyboard input in your app

元の動画を見る

ハイライト

iOS 15 では、UIKit コントロールでカメラを介してテキスト フィールドに現実のテキストを直接入力し、textContentTypekeyboardTypeそしてUIKeyInput何を認識するか、エントリがどこにあるか、誰がそれを受け取るかを制御します。

主要内容

旅行アプリでは、ユーザーに紙に情報を記入するよう求めることがよくあります。ホテルの電話番号は確認書に、住所は客室冊子に、アクティビティ時間はチラシに記載されています。以前は、ユーザーは紙を近づけてフォームに 1 文字ずつ入力することしかできませんでした。電話番号と住所がとても長いです。間違った数字を入力した場合は、戻って確認する必要があります。

iOS 15 では、Live Text とキーボード入力が統合されています。ユーザーがテキスト フィールドで [カメラからのテキスト] を開くと、システムがカメラを起動して画面内のテキストを認識し、ユーザーが選択したテキストを現在の入力位置に挿入します。デモで旅行日記アプリを使用して、ホテルの電話番号と住所を入力します。

最初のデモにはもう 1 つ問題がありました。カメラはドキュメント テキストのブロック全体を表示しますが、ユーザーは電話番号を選択するためにドラッグする必要があります。認識は成功しましたが、アプリはまだシステムにどのようなコンテンツが必要かを伝えていません。

Apple が提供する解決策は簡単です。既存のテキスト入力プロパティを使用します。textContentTypeそしてkeyboardType元々はオートフィルとキーボードレイアウトに使用されていました。 iOS 15 のカメラ入力もこれらのプロパティを読み取ります。フィールドが電話番号として宣言されている場合、システムは電話番号をフィルタリングします。フィールドが完全なアドレスとして宣言されている場合、システムはアドレスをフィルタリングします。

2つ目の問題は、入り口が隠れすぎていることです。編集メニューを表示するには 2 回目のクリックが必要で、候補バーには予測テキストが表示される場合があり、ユーザーはここでカメラが使用できることを必ずしも認識していない可能性があります。 iOS 15の新機能UIAction.captureTextFromCamera、開発者はカメラ入力をツールバー、メニュー、または独自のボタンに配置できます。

最後に、受信対象はこれに限定されません。UITextFieldそしてUITextView。レスポンダーが実装している限りUIKeyInput、カメラによって認識されたテキストは通過できますinsertText(_:)デモでは、UIImageViewサブクラスはカメラ テキストを受け取り、それを画像のタイトルとして表示します。

詳細

コンテンツ タイプごとにカメラ認識結果をフィルタリングする

(02:18) カメラ入力のフィルター依存関係TextContentTypeそしてKeyboardType。これらのプロパティはテキスト フィールドとテキスト ビューに存在します。オートフィル用にこれらのプロパティを設定したアプリは、iOS 15 のカメラ入力フィルタリングの恩恵を自動的に受けられるようになります。

(03:33) デモコードは以下の通りです。

phone.keyboardType = .phonePad
phone.autocorrectionType = .no

address.textContentType = .fullStreetAddress

キーポイント:

  • phone.keyboardType = .phonePad電話フィールドのキーボードを電話のキーパッドに設定します。
  • phone.autocorrectionType = .no自動補正をオフにします。自動修正または予測の候補がない場合、iOS は候補バーにカメラをすばやく開くためのボタンを提供します。
  • address.textContentType = .fullStreetAddress請求の住所フィールドには完全な番地が必要です。
  • カメラ入力がこれらの属性を読み取ると、一致しないテキストは無視され、ユーザーが手動で選択する手間が減ります。

(02:53) このスピーチには、フィルター可能なタイプが 7 つリストされています。最初の 4 つは既存のタイプです: 電話番号、完全な住所、URL、および電子メール。 iOS 15 では、フライト番号、荷物追跡番号、日付/時刻/期間が追加されます。

phone.textContentType = .telephoneNumber
address.textContentType = .fullStreetAddress
website.textContentType = .URL
email.textContentType = .emailAddress
flight.textContentType = .flightNumber
tracking.textContentType = .shipmentTrackingNumber
eventTime.textContentType = .dateTime

キーポイント:

  • .telephoneNumberまずカメラに電話番号をキャプチャさせます。
  • .fullStreetAddressまずカメラに完全なアドレスを取得させます。
  • .URLそして.emailAddress名刺やポスター、レシートなどからURLやメールを抽出するのに適しています。
  • .flightNumber旅行シナリオに適しており、搭乗券、電子メールの印刷物、旅程表などに適しています。
  • .shipmentTrackingNumber物流シナリオでは、速達注文や荷物のラベルに適しています。
  • .dateTimeイベントの時間、予約の時間、および期間を重視します。

カメラからのテキストを独自のエントリに挿入します

(04:21) システム編集メニューの [カメラからのテキスト] エントリは、必ずしも見つけやすいとは限りません。スピーチの [メモ] フィールドを 2 回クリックして編集メニューを表示する必要があり、候補列にも予測テキストが表示される場合があります。 Apple は、カメラ入力を積極的に促進したい場合には、専用のランチャーを追加することを推奨しています。

(05:07) iOS 15 は以下を提供しますUIAction.captureTextFromCamera(responder:identifier:)

let textFromCamera = UIAction.captureTextFromCamera(responder: self.notes, identifier: nil)

キーポイント:

  • UIAction.captureTextFromCameraシステムアクションを作成します。
  • responder: self.notes認識されたテキストが挿入されることを指定しますnotesこの回答者。
  • identifier: nilカスタム ID が提供されないことを示します。
  • このアクションにはタイトルと画像が付属しています。ボタンまたはメニューに配置すると、システムは一貫した表示スタイルを提供します。
  • タイトルはシステムによってローカライズされるため、開発者が自分で多言語コピーを作成する必要はありません。

(05:41) 他のカメラ関連アクションと同じメニューに配置できます。

let textFromCamera = UIAction.captureTextFromCamera(responder: self.notes, identifier: nil)

let choosePhotoOrVideo = UIAction(title: "Choose Photo or Video") { _ in
    presentPhotoPicker()
}

let takePhotoOrVideo = UIAction(title: "Take Photo or Video") { _ in
    presentCamera()
}

let scanDocuments = UIAction(title: "Scan Documents") { _ in
    presentDocumentScanner()
}

let cameraMenu = UIMenu(children: [
    choosePhotoOrVideo,
    takePhotoOrVideo,
    scanDocuments,
    textFromCamera
])

let menuToolbarItem = UIBarButtonItem(
    title: nil,
    image: UIImage(systemName: "camera.badge.ellipsis"),
    primaryAction: nil,
    menu: cameraMenu
)

キーポイント:

  • textFromCameraシステムカメラのテキスト入力アクションです。
  • choosePhotoOrVideotakePhotoOrVideoscanDocumentsアプリ内の既存のカメラまたはメディア アクションを表します。
  • UIMenu(children:)これらのアクションをメニューに結合します。
  • textFromCamera同じメニューのセットに配置することで、ユーザーはそれをカメラの機能の一部として理解できます。
  • UIBarButtonItem(..., menu:)ツールバーのボタンにメニューをアタッチします。

ポータルを表示する前に空き状況を確認してください

(06:29) 講義リマインダー、カメラ入力入口を追加する前に、最初に確認してくださいcanPerformAction(_:withSender:)UIAction内部的に呼び出されますUIResponderの上captureTextFromCameraこれは、切り取り、コピー、貼り付けなどの標準的な編集操作に似ており、コンテキストの影響を受けます。

let selector = #selector(UIResponder.captureTextFromCamera(_:))

if notes.canPerformAction(selector, withSender: nil) {
    let textFromCamera = UIAction.captureTextFromCamera(responder: notes, identifier: nil)
    cameraMenuItems.append(textFromCamera)
}

キーポイント:

  • #selector(UIResponder.captureTextFromCamera(_:))カメラのテキスト入力に対応するレスポンダーのアクションを表します。
  • notes.canPerformAction(selector, withSender: nil)現在のコンテキストがこのアクションをサポートしているかどうかをシステムに判断させます。
  • 戻るtrueユーザーに使用できないボタンが表示されるのを避けるために、後でポータルを作成して表示します。
  • 音声リストの前提条件には、デバイスのハードウェア サポート、テキスト挿入を処理できるレスポンダー、編集可能なテキスト フィールドまたはテキスト ビュー、およびユーザーの優先言語リスト内の少なくとも 1 つのサポート言語が含まれます。

カスタム ビューがカメラ入力を受信できるようにします

(08:26) テキスト コントロールは次を使用します。UIKeyInput。カメラが認識したテキストが通過しますinsertText(_:)応答者に渡されました。UITextInputからの拡張UIKeyInput、まだ通過できますsetMarkedText挿入するテキストのプレビューを提供します。プレビューはオプションの機能です。最終的なテキストのみを受け取りたい場合は、実装しますUIKeyInputそれで十分です。

(09:59) デモのピクチャータイトルビューはこんな感じで実装されています。

class HeadlineImageView: UIImageView, UIKeyInput {
    var headlineLabel: UILabel = UILabel()
    var hasText: Bool = false

    override init(image: UIImage?) {
        super.init(image: image)
        initializeLabel()
    }

    func insertText(_ text: String) {
        headlineLabel.text = text
    }

    func deleteBackward() { }
}

キーポイント:

  • HeadlineImageView継承するUIImageView, 元々の能力が絵表示に偏っています。
  • UIKeyInputテキスト入力の受信者として利用できるようにします。
  • headlineLabelカメラが認識したタイトルテキストを表示するために使用されます。
  • hasTextはいUIKeyInput必須の属性。講義の例ではカメラ入力のみが必要なので、次のように修正できます。false
  • insertText(_:)カメラから渡された文字列を受け取り、書き込むheadlineLabel.text
  • deleteBackward()はいUIKeyInput必要なメソッド。この例では削除ロジックが必要ないため、メソッド本体は空です。

(09:21) カスタム レスポンダーもフィルタリングに参加したい場合は、次のように使用できます。UITextInputTraitsを提供するため、keyboardTypeそしてtextContentTypeこのタイプのオプションの属性。

final class TrackingNumberView: UIView, UIKeyInput, UITextInputTraits {
    var label = UILabel()
    var hasText: Bool { label.text?.isEmpty == false }
    var textContentType: UITextContentType! = .shipmentTrackingNumber
    var keyboardType: UIKeyboardType = .asciiCapable

    func insertText(_ text: String) {
        label.text = text
    }

    func deleteBackward() {
        label.text = nil
    }
}

キーポイント:

  • UIKeyInput挿入されたテキストの受信を担当します。
  • UITextInputTraits入力機能の公開を担当します。
  • textContentType = .shipmentTrackingNumber最初に追跡番号を探すようにカメラに指示します。
  • keyboardType = .asciiCapableこの入力オブジェクトにキーボード タイプのヒントを与えます。
  • hasText現在のタグの内容に基づいてステータスを返します。
  • deleteBackward()ラベルの内容をクリアし、基本的な削除動作を完了します。

重要ポイント

  1. やるべきこと: 紙の情報スキャンをホテル、B&B、および会議のサインイン フォームに追加します。 実行する価値がある理由: このプレゼンテーションでは、チェックイン シート、確認書、フロント デスク情報をカバーする電話と住所のフィルタリングについて説明します。 開始方法: 電話フィールドを設定します.telephoneNumberそして.phonePad、アドレスフィールドを設定します.fullStreetAddress、 またUIAction.captureTextFromCameraフォームツールバーに配置します。

  2. やるべきこと: 速達番号を素早く入力するコンポーネントを作成します。 実行する価値がある理由: iOS 15 の新機能.shipmentTrackingNumber、カメラはパッケージラベルから追跡番号を除外できます。 開始方法: 入力コントロールを置きますtextContentTypeに設定.shipmentTrackingNumber、コントロールの隣にカメラボタンを置くと、ボタンがトリガーされますcaptureTextFromCamera

  3. やるべきこと: フライト番号のスキャンを旅行アプリに追加します。 実行する価値がある理由: スピーチでは次のように明確に述べられています。.flightNumber旅行アプリに最適で、ユーザーは搭乗券または旅程からフライトを入力できます。 開始方法: フライト フィールドのセットアップ.flightNumber、日付フィールドに設定.dateTime、カメラが便名と出発時刻を個別にフィルターできるようにします。

  4. やるべきこと: 写真のカバーにリアルなテキスト キャプションを追加します。 実行する価値がある理由: デモ内HeadlineImageViewピクチャービューも通過できることを説明するUIKeyInputカメラテキストを受信します。 開始方法: 作成するUIImageViewサブクラス、追加UILabel、成し遂げるinsertText(_:)、次に使用しますUIAction.captureTextFromCamera(responder: imageView, identifier: nil)入力を開始します。

  5. やるべきこと: イベント ポスター コレクション アプリに時間認識を追加します。 実行する価値がある理由: iOS 15 のカメラ フィルターは日付、時刻、期間をサポートしているため、ポスターやチラシからイベント時間を記録するのに適しています。 開始方法: 時間フィールドを入力しますtextContentTypeに設定.dateTime、認識が完了したら、その文字列を独自の日付解析ロジックに渡します。

関連セッション

コメント

GitHub Issues · utterances