UITableViewCell で Copy Paste メニューを表示する
UITableView
にはセルの Copy Paste メニューを簡単に実装できる delegate メソッドが用意されている。
// Copy/Paste. All three methods must be implemented by the delegate. - (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath NS_AVAILABLE_IOS(5_0); - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0); - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender NS_AVAILABLE_IOS(5_0);
ヘッダによればこの3つのメソッドを実装する必要があるとの事。
上の2つのメソッドで YES を返して最後のメソッドは空にすればとりあえずセルの長押し時に以下のようにメニューを表示させる事ができる。
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath { return YES; } - (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { return YES; } - (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { }
performAction: での条件分岐のためのセレクタの判定は NSStringFromSelector
で文字列にしてから isEqualToString:
メソッドで比較する以外に ==
でSEL型を直接比較する事もできる。
copy:
の時は表示コンテンツをペーストボードに保存paste:
の時はペーストボードの中身を表示コンテンツに反映cut:
の時は表示コンテンツをペーストボードに保存して表示コンテンツを削除
を実装するとひとまず動きが見られる状態になる。
上記のコードでは文字列 @"ABCDE"
から配列 @[@"A", @"B", @"C", @"D", @"E"]
を作成してテーブルに表示するコンテンツのリストとして使用している。
実際に動作させてみると以下の様に動く。
まずCのセルを長押ししてメニューを表示
Copy を選択
次のDのセルを長押し
Paste を選択
CのコンテンツがDに上書きされる
次にBのセルを長押し
今度は Cut を選択
Bが削除される
そしてAのセルを長押し
Paste を選択
BのコンテンツがAに上書きされる
実際には表示するコンテンツのモデルクラスによってアクションを動作させたりさせなかったり、オブジェクトの encode によるコピーを実装したり、アプリ用の UIPasteboard を使用したりといろいろ考慮すべき事はあるけどひとまず使用方法のサンプルとしてはこんなところ。
以下の様に引数に入って来る action を全てログ出力すると以下のように様々なアクションが入って来るのが分かる。
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender { NSLog(@"%@", NSStringFromSelector(action)); return YES; }
ログ
cut: copy: select: selectAll: paste: delete: _promptForReplace: _transliterateChinese: _showTextStyleOptions: _define: _addShortcut: _accessibilitySpeak: _accessibilitySpeakLanguageSelection: _accessibilityPauseSpeaking: makeTextWritingDirectionRightToLeft: makeTextWritingDirectionLeftToRight:
でもこの delegate メソッドを使う方法だとメニューの詳細なカスタマイズができず、実際にメニューとして表示される内容は framework 任せで Cut, Copy, Paste になってしまう模様。