Habilite copiar y pegar en UITextField sin hacerlo editable

Quiero que el texto en un UITextField (o, idealmente, un UILabel ) sea no editable , pero al mismo tiempo le dé al usuario la capacidad de copiarlo para pegarlo en otro lugar.

Mi solución final fue la siguiente:

Creé una subclase de UILabel (UITextField debería funcionar de la misma manera) que muestra un UIMenuController después de ser tocado. CopyableLabel.m se ve así:

 @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 

Esta pregunta es bastante antigua y me sorprende que nadie haya publicado una solución sin subclases. La idea presentada en la respuesta de @mrueg es correcta, pero no es necesario que subclasses nada. Me encontré con este problema y lo resolvió así:

En mi vista controlador:

 - (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; } 

Si quieres hacer que esto funcione para un UILabel , debería funcionar de la misma manera con solo agregar un reconocedor de gestos de toque en lugar de usar el método de delegado.

Pruebe UITextView en UITextView lugar (sospecho que funcionaría como un UILabel para usted). Probé esto con su propiedad editable establecida en NO , y el doble toque para copiar funcionó para mí.

Otra solución es mantener el UITextField habilitado pero evitando que se UITextField programáticamente. Esto se hace con el siguiente método delegado:

 - (BOOL)textField:(UITextField *)textField shouldChangeCharactersInRange:(NSRange)range replacementString:(NSString *)string { return NO; } 

Sin embargo, no estoy al tanto de las posibles limitaciones, actualmente se adapta a mis necesidades.

Esto hará todo lo que necesites. Se puede copiar. Pero no editable, y no mostrará un teclado o un 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 } } 

El siguiente código me salvó.

 textField.addTarget(target, action: "textFieldEditingDidEndAction:", forControlEvents: [.EditingDidEnd]) 

Parece que Paste es un evento de edición único y completo.