views:

1528

answers:

2

I will admit that there is already a question exactly along these lines here on S.O., but it lacks implementation details, a working answer, and I would like to be more specific, so I think a new question is in order. Obviously, let me know if I'm wrong and we can try to restart the thread over there.

Basically, I want to copy the text in a UILabel to the pasteboard when a user holds down on the label. Not hard to do, honestly. However, I think the best way to provide visual feedback is to prompt the user with the Copy menu option from UIMenuController.

According to the Event Handling section of the iPhone Application Programming Guide, specifically the section on Copy, Cut, and Paste Operations, it should be possible to provide copy, cut, and/or paste operations from a custom view.

So, I've sub-classed UILabel with the following implementation as described by the guide, but the UIMenuController won't show up. There's no indication in the guide that there's anything else required to do this, and the NSLog statement does print out to the console, indicating that the selector is being performed when I hold down on the label:

//
//  CopyLabel.m
//  HoldEm
//
//  Created by Billy Gray on 1/20/10.
//  Copyright 2010 Zetetic LLC. All rights reserved.
//

#import "CopyLabel.h"

@implementation CopyLabel

- (void)showCopyMenu {
    NSLog(@"I'm tryin' Ringo, I'm tryin' reeeeal hard.");
    // bring up editing menu.
    UIMenuController *theMenu = [UIMenuController sharedMenuController];
    // do i even need to show a selection? There's really no point for my implementation...
    // doing it any way to see if it helps the "not showing up" problem...
    CGRect selectionRect = [self frame];
    [theMenu setTargetRect:selectionRect inView:self];
    [theMenu setMenuVisible:YES animated:YES]; // <-- doesn't show up...
}

// obviously, important to provide this, but whether it's here or not doesn't seem
// to change the fact that the UIMenuController view is not showing up
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
    BOOL answer = NO;

    if (action == @selector(copy:))
        answer = YES;

    return answer;
}

- (BOOL)canBecomeFirstResponder {
    return YES;
}

- (void)touchesBegan:(NSSet *)touches withEvent:(UIEvent *)event {
    [self performSelector:@selector(showCopyMenu) withObject:nil afterDelay:0.8f];
}

- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showCopyMenu) object:nil];
}

- (void)touchesCancelled:(NSSet *)touches withEvent:(UIEvent *)event {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showCopyMenu) object:nil];
}

- (void)touchesMoved:(NSSet *)touches withEvent:(UIEvent *)event {
    [NSObject cancelPreviousPerformRequestsWithTarget:self selector:@selector(showCopyMenu) object:nil];
}

@end

So, what else does one have to do to make this happen?

For those following along and trying to do this, too, you'll also need to set 'User Interaction Enabled' for the label

Edit:

For clarity, let me add that this should be similar to the little [Copy] menu item that appears over an image in certain iphone views when you hold down on it. -B

+4  A: 

I'll say upfront I don't have an aswer, but I did some poking around and found more out. I'm sure you've looked at this already: CopyPasteTile

That code does work on my simulator and goes like this:

CGRect drawRect = [self rectFromOrigin:currentSelection inset:TILE_INSET];
[self setNeedsDisplayInRect:drawRect];

UIMenuController *theMenu = [UIMenuController sharedMenuController];
[theMenu setTargetRect:drawRect inView:self];
[theMenu setMenuVisible:YES animated:YES];

There are a few differences here:

  • drawRect is calculated from a giant view tile and tap point calculations
  • setNeedsDisplayInRect is being called
  • self is a large screen sized view, you may need screen coords instead of local coords (you can probably get that from self.superview)

I'd try making these adjustments to match the example first and see what kind of progress it gets me.

slf
aaahhh, interesting! will give it a shot, thanks ;-)
Billy Gray
BINGO, tried each of your suggestions, and the winner was setting the `selectionRect = [[super view] frame]`. Will write up a complete working example and link it form here soon. Thanks!
Billy Gray
glad to hear you got it fixed :)
slf
So Billy - Where's the complete example? :-)
amok
+1  A: 

Could you post your solution? I'm having a similar problem with a UITableView controller where I'm trying to allow the user to select and copy a UITableViewCell.

Ben
If you want to pop up the `uiMenuController` in response to `tableView:didSelectRowAtIndexPath:`, you don't necessarily know what cell to place it on, since you don't have a reference to it.I think in your particular situation you want to subclass UITableView and over-ride the various `touches` implementations, which intercept all touches to the table view's subviews to implement a lot of that handy default functionality.This guy over here has an awesome multi-post tutorial in the forum describing how he handled it:http://forums.macrumors.com/showthread.php?t=640508
Billy Gray