UILabel实现长按复制功能

1. 创建 UILabel 的子类

@interface YYCopyLabel : UILabel

@property (nonatomic, assign) BOOL copyEnabled;

@end

2. 增加 UILongPressGestureRecognizer 手势

- (void)setCopyEnabled:(BOOL)copyEnabled
{
    _copyEnabled = copyEnabled;
    
    // 确保 UILabel 可交互
    self.userInteractionEnabled = copyEnabled;
    
    if (copyEnabled && !self.longPressGR) {
        self.longPressGR = [[UILongPressGestureRecognizer alloc] initWithTarget:self
                                                                         action:@selector(handleLongPressGesture:)];
        [self addGestureRecognizer:self.longPressGR];
    }
    
    if (self.longPressGR) {
        self.longPressGR.enabled = copyEnabled;
    }
}

- (void)handleLongPressGesture:(UILongPressGestureRecognizer *)longPressGR
{
    if (longPressGR.state == UIGestureRecognizerStateBegan) {
        [self becomeFirstResponder];
        [[UIMenuController sharedMenuController] setTargetRect:self.frame inView:self.superview];
        [[UIMenuController sharedMenuController] setMenuVisible:YES animated:YES];
    }
}

3. 实现 UIMenuController 的相关协议

- (BOOL)canBecomeFirstResponder
{
    return YES;
}

- (BOOL)canPerformAction:(SEL)action withSender:(id)sender
{
    // 自定义响应UIMenuItem Action,例如你可以过滤掉多余的系统自带功能(剪切,选择等),只保留复制功能。
    return (action == @selector(copy:));
}

- (void)copy:(id)sender
{
    [[UIPasteboard generalPasteboard] setString:self.text];
}

4. 使用UIMenuController出现UIViewControllerHierarchyInconsistency crash

  • Exception log: UICompatibilityInputViewController的父控制器必须是UIInputWindowController,不能是其他自定义的控制器。
'UIViewControllerHierarchyInconsistency', reason: 'child view controller: should have parent view controller: but requested parent is:'
  • 崩溃原因:调用UIMenuController控制器的视图层级树(view tree)存在命名为inputView的view。上面例子是因为ClipboardLabelViewController 定义了inputView。
@property (nonatomic, strong) UIView *inputView;
  • 解决办法:找出自定义inputView,修改其命名,例如你可以改成myInputView

5. YYCopyLabelDemo

你可能感兴趣的:(UILabel实现长按复制功能)