TL;DR
- ●バーコードリーダーは外部キーボードとして扱える
- ●
UITextField
などの入力コンポーネントを使って入力を受け取れる - ●
UITextField
などを使いたくない場合がある - ●
UIKeyCommand
を使うと入力コンポーネントを使わずに入力を受け取れる
ユビレジでは商品の入力に市販のバーコードリーダーを利用することができます。
一般的なBluetoothのバーコードリーダーはHID(Human Interface Device)とSPP(Serial Port Profile)の両方のプロファイルに対応しています。
HIDとして接続する場合は外部キーボードと同じ扱いになります。
外部キーボードが繋がっているのと同じなので、UITextField
やUITextView
を使って特別なSDKを必要とせずに入力を受け取ることができます。
ただし、このやり方は簡単なのですが、入力を受け取るにはUITextField
などの入力コンポーネントがアクティブになっている必要があるので少し不便です。
ユビレジでは商品点数の多い小売の店舗などではバーコードリーダーメインの入力として使っていますが、飲食店などではバーコードリーダーはまったく使いません。 このように利用者によって、使うところはメインの入力で使うし、使わないところはまったく使わないという状況なので、どちらにも使いやすくなっている必要があります。
そのため、バーコードリーダーの入力を受けるためにはテキスト入力エリアをタップする必要がある、というのは常時バーコードリーダーを利用するユーザーは面倒に感じるでしょう。 かといって常にテキスト入力エリアが自動的にアクティブになるようにすると、バーコードリーダーが接続されてない店舗では常にソフトウェアキーボードが表示されてしまいます。
そこで、ユビレジではバーコードリーダーの入力を受け取るのにUIKeyCommand
というiOS 7から新しく追加されたAPIを利用しています。
UIKeyCommand
は本来は外部キーボードが接続された状態でキーボードショートカットによる操作をサポートするためのAPIです。
任意のキー入力の組み合わせを受け取ることができるので、入力される可能性のあるすべての文字に反応するようにしておくことで、任意のキー入力を受け取る仕組みとして利用することができます。
UIKeyCommand
については前に別の記事でも書きましたのでそちらもご覧ください。
iOSアプリケーションでキーボードショートカットに対応する - 24/7 twenty-four seven
例えば一般的なバーコードリーダーの入力を受け取るには下記のように実装します。
@interface ViewController () @property (nonatomic) NSArray *commands; @property (nonatomic) NSString *barcode; @end @implementation ViewController - (BOOL)canBecomeFirstResponder { return YES; } - (NSArray *)keyCommands { if (!self.commands) { NSMutableArray *commands = [[NSMutableArray alloc] init]; NSArray *characterSets = @[[NSCharacterSet characterSetWithRange:NSMakeRange(0x20, 0x7f - 0x20)], [NSCharacterSet newlineCharacterSet]]; for (unichar i = 0x00; i < 0x7f; i++) { for (NSCharacterSet *characterSet in characterSets) { if ([characterSet characterIsMember:i]) { NSString *string = [[NSString alloc] initWithCharacters:&i length:1]; UIKeyCommand *command = [UIKeyCommand keyCommandWithInput:string modifierFlags:kNilOptions action:@selector(handleKeyCommand:)]; [commands addObject:command]; break; } } } self.commands = commands.copy; } return self.commands; } - (void)handleKeyCommand:(UIKeyCommand *)command { NSString *key = command.input; NSCharacterSet *newlineCharacterSet = [NSCharacterSet newlineCharacterSet]; if ([key rangeOfCharacterFromSet:newlineCharacterSet].location != NSNotFound) { NSLog(@"Barcode: %@", self.barcode); self.barcode = nil; } else { if (self.barcode) { self.barcode = [self.barcode stringByAppendingString:key]; } else { self.barcode = key; } } } @end
まず、UIKeyCommand
でキー入力を受け取るにはcanBecomeFirstResponder
メソッドでYES
を返す必要があります。
そしてkeyCommands
プロパティをオーバーライドして、受け取りたいキーコンビネーションのUIKeyCommand
インスタンスの配列を返すようにします。
上記の例ではすべてのASCII文字と、改行文字に反応します。
これで接続されたバーコードリーダーでバーコードを読み取るたびにhandleKeyCommand:
メソッドが呼ばれます。
handleKeyCommand:
メソッドは1文字ずつ連続で呼ばれるので、終わりが来るまで読み取った文字列を結合します。
たいていのバーコードリーダーでは終わりに改行文字を送ってくるため、それをバーコードの終わりと判断して、そこまでを一つのバーコードと扱います。
このコードはバーコードリーダーが接続されてない場合にはまったく影響ありません。
このように、UIKeyCommand
を利用すると、バーコードリーダーを利用している場合は特別な操作を必要とせずにバーコードリーダーからの入力を受け取ることができ、利用しない場合は今までどおり使えるという先述の問題をキレイに解決することができます。
マイナーなAPIですが、意外と便利で、おそらくバーコードリーダー以外にも応用できる場面はあるのではないかと思います。