Я хочу, чтобы текст в UITextField
(или, в идеале, UILabel
) был нередактируемым, но в то же время предоставлял пользователю возможность скопировать его, чтобы вставить его в другое место.
Включить копирование и вставку на UITextField, не делая его редактируемым
Ответ 1
Моим окончательным решением было следующее:
Я создал подкласс 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
Ответ 2
Этот вопрос довольно старый, и я удивлен, что никто не опубликовал решение без подкласса. Идея, представленная в ответе @mrueg, верна, но вам не нужно ничего подклассифицировать. Я просто столкнулся с этой проблемой и решил ее так:
На мой взгляд, контроллер:
- (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;
}
Если вы хотите сделать эту работу для UILabel
, она должна работать так же, как только добавить распознаватель жестов, вместо использования метода делегата.
Ответ 3
Попробуйте UITextView
вместо этого (я подозреваю, что он будет работать как UILabel
для вас). Я тестировал это со свойством editable
, установленным в NO
, и для меня работало двойное нажатие-копирование.
Ответ 4
Другое решение поддерживает UITextField
, но программно не позволяет редактировать его. Это делается с помощью следующего метода делегата:
- (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string
{
return NO;
}
Я не знаю о возможных ограничениях, хотя в настоящее время это соответствует моим потребностям.
Ответ 5
Следующий код сохранил меня.
textField.addTarget(target, action: "textFieldEditingDidEndAction:", forControlEvents: [.EditingDidEnd])
Кажется, что Paste
- одно и то же событие редактирования.
Ответ 6
Это сделает все, что вам нужно. Будет скопирован. Но не редактируется, и не будет отображаться клавиатура или курсор.
class ViewController: UIViewController {
@IBOutlet weak var copyableUneditableTextfield: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
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
}
}