Is there a simple way for subclasses of UITableViewCell to show the 'Copy' UIMenuController popup like in the Address book app (see screenshot), after the selection is held for a while?
The method before iOS 5 is to get the UIMenuController's shared instance, set the target rect and view and call -setMenuVisible:animated:
. Remeber to implement -canPerformAction:withSender:
in your responder.
The method after iOS 5 (previously available as undocumented feature) is to implement these 3 methods in your data source (see https://developer.apple.com/reference/uikit/uitableviewdelegate#1653389).
-(void)tableView:(UITableView*)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath*)indexPath withSender:(id)sender;
-(BOOL)tableView:(UITableView*)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath*)indexPath withSender:(id)sender;
-(BOOL)tableView:(UITableView*)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath*)indexPath;
There is now official interface for displaying UITableView cell menus in iOS 5. Example (from the table delegate):
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
return (action == @selector(copy:));
}
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:)){
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
[[UIPasteboard generalPasteboard] setString:cell.textLabel.text];
}
}
I tried modifying the UIMenuController's shared controller to add my own menu item, and I was able to add it and get the canPerformAction
message for it, but returning YES didn't help; I wasn't able to make my custom menu item appear. From my experiments, it looks like only Copy, Cut, and Paste are supported. [EDIT Since this was posted, I've learned how to add custom menu items.]
Note that this works only if all three delegate methods are implemented.
Here is the Swift syntax for copying detailTextLabel
.
func tableView(_ tableView: UITableView, shouldShowMenuForRowAt indexPath: IndexPath) -> Bool {
return (tableView.cellForRow(at: indexPath)?.detailTextLabel?.text) != nil
}
func tableView(_ tableView: UITableView, canPerformAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) -> Bool {
return action == #selector(copy(_:))
}
func tableView(_ tableView: UITableView, performAction action: Selector, forRowAt indexPath: IndexPath, withSender sender: Any?) {
if action == #selector(copy(_:)) {
let cell = tableView.cellForRow(at: indexPath)
let pasteboard = UIPasteboard.general
pasteboard.string = cell?.detailTextLabel?.text
}
}
Your UITableViewCell subclass may look like this
@interface MenuTableViewCell : UITableViewCell {
}
- (IBAction)copy:(id)sender;
- (void)showMenu;
@end
@implementation MenuTableViewCell
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
if (action == @selector(copy:)) {
return YES;
}
return NO;
}
- (IBAction)copy:(id)sender {
}
- (void)showMenu {
[[UIMenuController sharedMenuController] setMenuVisible:NO animated:YES];
[self becomeFirstResponder];
[[UIMenuController sharedMenuController] update];
[[UIMenuController sharedMenuController] setTargetRect:CGRectZero inView:self];
[[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
}
@end
And the UITableView delegate methods are like
- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
static NSString *CellIdentifier = @"Cell";
MenuTableViewCell *cell = (MenuTableViewCell *)[tableView dequeueReusableCellWithIdentifier:CellIdentifier];
if (cell == nil) {
cell = [[[MenuTableViewCell alloc] initWithStyle:UITableViewCellStyleDefault reuseIdentifier:CellIdentifier] autorelease];
}
// Configure the cell.
return cell;
}
- (void)tableView:(UITableView *)tableView didSelectRowAtIndexPath:(NSIndexPath *)indexPath {
MenuTableViewCell *cell = (MenuTableViewCell *)[tableView cellForRowAtIndexPath:indexPath];
[cell showMenu];
}
#pragma mark - COPY/PASTE Cell Text via Menu
- (BOOL)tableView:(UITableView *)tableView shouldShowMenuForRowAtIndexPath:(NSIndexPath *)indexPath
{
return YES;
}
- (BOOL)tableView:(UITableView *)tableView canPerformAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
return (action == @selector(copy:));
}
- (void)tableView:(UITableView *)tableView performAction:(SEL)action forRowAtIndexPath:(NSIndexPath *)indexPath withSender:(id)sender
{
if (action == @selector(copy:))
{
UITableViewCell *cell = [tableView cellForRowAtIndexPath:indexPath];
UIPasteboard *pasteBoard = [UIPasteboard generalPasteboard];
[pasteBoard setString:cell.textLabel.text];
}
}
来源:https://stackoverflow.com/questions/2487844/simple-way-to-show-the-copy-popup-on-uitableviewcells-like-the-address-book-ap