ios 在 UITextField 上启用复制和粘贴而不使其可编辑
声明:本页面是StackOverFlow热门问题的中英对照翻译,遵循CC BY-SA 4.0协议,如果您需要使用它,必须同样遵循CC BY-SA许可,注明原文地址和作者信息,同时你必须将它归于原作者(不是我):StackOverFlow
原文地址: http://stackoverflow.com/questions/1920541/
Warning: these are provided under cc-by-sa 4.0 license. You are free to use/share it, But you must attribute it to the original authors (not me):
StackOverFlow
Enable copy and paste on UITextField without making it editable
提问by mrueg
I want the text in a UITextField(or ideally, a UILabel) to be non-editable, but at the same time give the user the ability to copy it to paste elsewhere.
我希望 a UITextField(或理想情况下, a UILabel)中的文本是不可编辑的,但同时让用户能够将其复制粘贴到其他地方。
回答by mrueg
My final solution was the following:
我的最终解决方案如下:
I created a subclass of UILabel (UITextField should work the same) that displays a UIMenuController after being tapped. CopyableLabel.m looks like this:
我创建了一个 UILabel 的子类(UITextField 应该工作相同),它在被点击后显示一个 UIMenuController。CopyableLabel.m 看起来像这样:
@implementation CopyableLabel
- (BOOL)canPerformAction:(SEL)action withSender:(id)sender {
if(action == @selector(copy:)) {
return YES;
}
else {
return [super canPerformAction:action withSender:sender];
}
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (BOOL)becomeFirstResponder {
if([super becomeFirstResponder]) {
self.highlighted = YES;
return YES;
}
return NO;
}
- (void)copy:(id)sender {
UIPasteboard *board = [UIPasteboard generalPasteboard];
[board setString:self.text];
self.highlighted = NO;
[self resignFirstResponder];
}
- (void)touchesEnded:(NSSet *)touches withEvent:(UIEvent *)event {
if([self isFirstResponder]) {
self.highlighted = NO;
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setMenuVisible:NO animated:YES];
[menu update];
[self resignFirstResponder];
}
else if([self becomeFirstResponder]) {
UIMenuController *menu = [UIMenuController sharedMenuController];
[menu setTargetRect:self.bounds inView:self];
[menu setMenuVisible:YES animated:YES];
}
}
@end
回答by Shinigami
This question is pretty old and I'm surprised nobody has posted a solution without subclassing. The idea presented in @mrueg's answer is correct, but you shouldn't need to subclass anything. I just came across this problem and solved it like this:
这个问题已经很老了,我很惊讶没有人发布没有子类化的解决方案。@mrueg 的答案中提出的想法是正确的,但您不需要对任何内容进行子类化。我刚刚遇到这个问题并解决了这个问题:
In my view controller:
在我的视图控制器中:
- (void)viewDidLoad {
self.textField.delegate = self;
self.textField.text = @"Copyable, non-editable string.";
}
- (BOOL)canBecomeFirstResponder {
return YES;
}
- (void)copyTextFieldContent:(id)sender {
UIPasteboard* pb = [UIPasteboard generalPasteboard];
pb.string = self.textField.text;
}
- (BOOL)textFieldShouldBeginEditing:(UITextField *)textField {
// UIKit changes the first responder after this method, so we need to show the copy menu after this method returns.
dispatch_after(dispatch_time(DISPATCH_TIME_NOW, (int64_t)(0.3*NSEC_PER_SEC)), dispatch_get_main_queue(), ^{
[self becomeFirstResponder];
UIMenuController* menuController = [UIMenuController sharedMenuController];
UIMenuItem* copyItem = [[UIMenuItem alloc] initWithTitle:@"Copy"
action:@selector(copyTextFieldContent:)];
menuController.menuItems = @[copyItem];
CGRect selectionRect = textField.frame;
[menuController setTargetRect:selectionRect inView:self.view];
[menuController setMenuVisible:YES animated:YES];
});
return NO;
}
If you want to make this work for a UILabel, it should work the same way with just adding a tap gesture recognizer instead of using the delegate method.
如果你想让UILabel它为 a 工作,它应该以相同的方式工作,只需添加一个点击手势识别器而不是使用委托方法。
回答by Harris
This will do everything you need. Will be copyable. But not editable, and won't show a keyboard or a cursor.
这将完成您需要的一切。将是可复制的。但不可编辑,也不会显示键盘或光标。
class ViewController: UIViewController {
@IBOutlet weak var copyableUneditableTextfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
copyableUneditableTextfield.delegate = self
copyableUneditableTextfield.inputView = UIView() //prevents keyboard
copyableUneditableTextfield.tintColor = .clear //prevents cursor
copyableUneditableTextfield.text = "Some Text You Want User To Copy But Not Edit"
}
}
extension ViewController: UITextFieldDelegate {
func textField(_ textField: UITextField, shouldChangeCharactersIn range: NSRange, replacementString string: String) -> Bool {
return false //prevents editing
}
}
回答by Alex Reynolds
Try UITextViewinstead (I suspect it would work like a UILabelfor you). I tested this with its editableproperty set to NO, and double-tapping-to-copy worked for me.
试试吧UITextView(我怀疑它会像UILabel你一样工作)。我测试了它的editable属性设置为NO,双击复制对我有用。
回答by keeshux
Another solution is keeping the UITextFieldenabled but programmatically preventing it from being edited. This is done with the following delegate method:
另一种解决方案是保持UITextField启用但以编程方式阻止它被编辑。这是通过以下委托方法完成的:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return NO;
}
I'm not aware of possible limitations though, currently suits my needs.
我不知道可能的限制,但目前适合我的需求。
回答by Veight Zhou
The following code saved me.
以下代码救了我。
textField.addTarget(target, action: "textFieldEditingDidEndAction:", forControlEvents: [.EditingDidEnd])
It seems Pasteis a single and complete edit event.
这似乎Paste是一个单一且完整的编辑事件。

