Marcador de posición en UITextView

Estoy haciendo una aplicación que utiliza una UITextView . Ahora quiero que UITextView tenga un marcador de posición similar al que puede establecer para un UITextField .

¿Alguien sabe como hacer esto?

Hice algunas modificaciones menores a la solución de bcd para permitir la inicialización de un archivo Xib , el Xib texto y mantener el color de fondo. Con suerte, salvará a otros el problema.

UIPlaceHolderTextView.h:

 #import  IB_DESIGNABLE @interface UIPlaceHolderTextView : UITextView @property (nonatomic, retain) IBInspectable NSString *placeholder; @property (nonatomic, retain) IBInspectable UIColor *placeholderColor; -(void)textChanged:(NSNotification*)notification; @end 

UIPlaceHolderTextView.m:

 #import "UIPlaceHolderTextView.h" @interface UIPlaceHolderTextView () @property (nonatomic, retain) UILabel *placeHolderLabel; @end @implementation UIPlaceHolderTextView CGFloat const UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION = 0.25; - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; #if __has_feature(objc_arc) #else [_placeHolderLabel release]; _placeHolderLabel = nil; [_placeholderColor release]; _placeholderColor = nil; [_placeholder release]; _placeholder = nil; [super dealloc]; #endif } - (void)awakeFromNib { [super awakeFromNib];  // Use Interface Builder User Defined Runtime Attributes to set  // placeholder and placeholderColor in Interface Builder. if (!self.placeholder) { [self setPlaceholder:@""]; } if (!self.placeholderColor) { [self setPlaceholderColor:[UIColor lightGrayColor]]; } [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil]; } - (id)initWithFrame:(CGRect)frame { if( (self = [super initWithFrame:frame]) ) { [self setPlaceholder:@""]; [self setPlaceholderColor:[UIColor lightGrayColor]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil]; } return self; } - (void)textChanged:(NSNotification *)notification { if([[self placeholder] length] == 0) { return; } [UIView animateWithDuration:UI_PLACEHOLDER_TEXT_CHANGED_ANIMATION_DURATION animations:^{ if([[self text] length] == 0) { [[self viewWithTag:999] setAlpha:1]; } else { [[self viewWithTag:999] setAlpha:0]; } }]; } - (void)setText:(NSString *)text { [super setText:text]; [self textChanged:nil]; } - (void)drawRect:(CGRect)rect { if( [[self placeholder] length] > 0 ) { if (_placeHolderLabel == nil ) { _placeHolderLabel = [[UILabel alloc] initWithFrame:CGRectMake(8,8,self.bounds.size.width - 16,0)]; _placeHolderLabel.lineBreakMode = NSLineBreakByWordWrapping; _placeHolderLabel.numberOfLines = 0; _placeHolderLabel.font = self.font; _placeHolderLabel.backgroundColor = [UIColor clearColor]; _placeHolderLabel.textColor = self.placeholderColor; _placeHolderLabel.alpha = 0; _placeHolderLabel.tag = 999; [self addSubview:_placeHolderLabel]; } _placeHolderLabel.text = self.placeholder; [_placeHolderLabel sizeToFit]; [self sendSubviewToBack:_placeHolderLabel]; } if( [[self text] length] == 0 && [[self placeholder] length] > 0 ) { [[self viewWithTag:999] setAlpha:1]; } [super drawRect:rect]; } @end 

De manera fácil, solo cree texto de marcador de posición en UITextView utilizando los siguientes métodos UITextViewDelegate :

 - (void)textViewDidBeginEditing:(UITextView *)textView { if ([textView.text isEqualToString:@"placeholder text here..."]) { textView.text = @""; textView.textColor = [UIColor blackColor]; //optional } [textView becomeFirstResponder]; } - (void)textViewDidEndEditing:(UITextView *)textView { if ([textView.text isEqualToString:@""]) { textView.text = @"placeholder text here..."; textView.textColor = [UIColor lightGrayColor]; //optional } [textView resignFirstResponder]; } 

solo recuerde configurar myUITextView con el texto exacto en la creación, por ejemplo

 UITextView *myUITextView = [[UITextView alloc] init]; myUITextView.delegate = self; myUITextView.text = @"placeholder text here..."; myUITextView.textColor = [UIColor lightGrayColor]; //optional 

y hacer que la clase padre sea un UITextViewDelegate antes de incluir estos métodos, por ejemplo

 @interface MyClass ()  @end 

Código para Swift 3.1

 func textViewDidBeginEditing(_ textView: UITextView) { if (textView.text == "placeholder text here...") { textView.text = "" textView.textColor = .black } textView.becomeFirstResponder() //Optional } func textViewDidEndEditing(_ textView: UITextView) { if (textView.text == "") { textView.text = "placeholder text here..." textView.textColor = .lightGray } textView.resignFirstResponder() } 

solo recuerde configurar myUITextView con el texto exacto en la creación, por ejemplo

  let myUITextView = UITextView.init() myUITextView.delegate = self myUITextView.text = "placeholder text here..." myUITextView.textColor = .lightGray 

y hacer que la clase padre sea un UITextViewDelegate antes de incluir estos métodos, por ejemplo

 class MyClass: UITextViewDelegate { } 

No estaba muy contento con ninguna de las soluciones publicadas, ya que eran un poco pesadas. Agregar vistas a la vista no es realmente ideal (especialmente en drawRect: . Ambos tenían filtraciones, lo cual tampoco es aceptable.

Aquí está mi solución: SAMTextView

SAMTextView.h

 // // SAMTextView.h // SAMTextView // // Created by Sam Soffes on 8/18/10. // Copyright 2010-2013 Sam Soffes. All rights reserved. // #import  /** UITextView subclass that adds placeholder support like UITextField has. */ @interface SAMTextView : UITextView /** The string that is displayed when there is no other text in the text view. The default value is `nil`. */ @property (nonatomic, strong) NSString *placeholder; /** The color of the placeholder. The default is `[UIColor lightGrayColor]`. */ @property (nonatomic, strong) UIColor *placeholderTextColor; /** Returns the drawing rectangle for the text views's placeholder text. @param bounds The bounding rectangle of the receiver. @return The computed drawing rectangle for the placeholder text. */ - (CGRect)placeholderRectForBounds:(CGRect)bounds; @end 

SAMTextView.m

 // // SAMTextView.m // SAMTextView // // Created by Sam Soffes on 8/18/10. // Copyright 2010-2013 Sam Soffes. All rights reserved. // #import "SAMTextView.h" @implementation SAMTextView #pragma mark - Accessors @synthesize placeholder = _placeholder; @synthesize placeholderTextColor = _placeholderTextColor; - (void)setText:(NSString *)string { [super setText:string]; [self setNeedsDisplay]; } - (void)insertText:(NSString *)string { [super insertText:string]; [self setNeedsDisplay]; } - (void)setAttributedText:(NSAttributedString *)attributedText { [super setAttributedText:attributedText]; [self setNeedsDisplay]; } - (void)setPlaceholder:(NSString *)string { if ([string isEqual:_placeholder]) { return; } _placeholder = string; [self setNeedsDisplay]; } - (void)setContentInset:(UIEdgeInsets)contentInset { [super setContentInset:contentInset]; [self setNeedsDisplay]; } - (void)setFont:(UIFont *)font { [super setFont:font]; [self setNeedsDisplay]; } - (void)setTextAlignment:(NSTextAlignment)textAlignment { [super setTextAlignment:textAlignment]; [self setNeedsDisplay]; } #pragma mark - NSObject - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self name:UITextViewTextDidChangeNotification object:self]; } #pragma mark - UIView - (id)initWithCoder:(NSCoder *)aDecoder { if ((self = [super initWithCoder:aDecoder])) { [self initialize]; } return self; } - (id)initWithFrame:(CGRect)frame { if ((self = [super initWithFrame:frame])) { [self initialize]; } return self; } - (void)drawRect:(CGRect)rect { [super drawRect:rect]; if (self.text.length == 0 && self.placeholder) { rect = [self placeholderRectForBounds:self.bounds]; UIFont *font = self.font ? self.font : self.typingAttributes[NSFontAttributeName]; // Draw the text [self.placeholderTextColor set]; [self.placeholder drawInRect:rect withFont:font lineBreakMode:NSLineBreakByTruncatingTail alignment:self.textAlignment]; } } #pragma mark - Placeholder - (CGRect)placeholderRectForBounds:(CGRect)bounds { // Inset the rect CGRect rect = UIEdgeInsetsInsetRect(bounds, self.contentInset); if (self.typingAttributes) { NSParagraphStyle *style = self.typingAttributes[NSParagraphStyleAttributeName]; if (style) { rect.origin.x += style.headIndent; rect.origin.y += style.firstLineHeadIndent; } } return rect; } #pragma mark - Private - (void)initialize { [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:self]; self.placeholderTextColor = [UIColor colorWithWhite:0.702f alpha:1.0f]; } - (void)textChanged:(NSNotification *)notification { [self setNeedsDisplay]; } @end 

Es mucho más simple que los demás, ya que no usa subvistas (o tiene filtraciones). Sientase libre de usarlo.

Actualización 11/10/11: ahora está documentado y es compatible con el uso en Interface Builder.

Actualización 24/11/13: apuntar a nuevo repository.

Lo que puede hacer es configurar la vista de texto con algún valor inicial en la propiedad del text , y cambiar el textColor a [UIColor grayColor] o algo similar. Luego, cada vez que la vista de texto se vuelva editable, borre el texto y presente un cursor, y si el campo de texto vuelve a estar vacío, vuelva a colocar el marcador de posición. Cambie el color a [UIColor blackColor] según corresponda.

No es exactamente lo mismo que la funcionalidad de marcador de posición en un UITextField, pero está cerca.

Me encontré una manera muy fácil de imitar a un poseedor de lugar

  1. en el NIB o código configure textView’s textColor en lightGrayColor (la mayoría de las veces)
  2. asegúrese de que su delegado de textView esté vinculado al propietario del archivo e implemente UITextViewDelegate en su archivo de encabezado
  3. establece el texto predeterminado de tu vista de texto en (ejemplo: “marcador de posición Foobar”)
  4. implementar: (BOOL) textViewShouldBeginEditing: (UITextView *) textView

Editar:

Se cambiaron las declaraciones if para comparar tags en lugar de texto. Si el usuario borró su texto, también fue posible eliminar accidentalmente una parte del @"Foobar placeholder" . Esto significaba que si el usuario volvía a ingresar el texto, vea el siguiente método de delegado, -(BOOL) textViewShouldBeginEditing:(UITextView *) textView , no funcionaría como se esperaba. Traté de comparar por el color del texto en la statement if, pero encontré que el color gris claro establecido en el constructor de interfaz no es lo mismo que el color gris claro establecido en el código con [UIColor lightGreyColor]

 - (BOOL) textViewShouldBeginEditing:(UITextView *)textView { if(textView.tag == 0) { textView.text = @""; textView.textColor = [UIColor blackColor]; textView.tag = 1; } return YES; } 

También es posible restablecer el texto del marcador de posición cuando el teclado vuelve y la [longitud del texto] == 0

EDITAR:

Para aclarar la última parte, así es cómo puede volver a establecer el texto del marcador de posición:

 - (void)textViewDidChange:(UITextView *)textView { if([textView.text length] == 0) { textView.text = @"Foobar placeholder"; textView.textColor = [UIColor lightGrayColor]; textView.tag = 0; } } 

Puede establecer la etiqueta en el UITextView por

 [UITextView addSubView:lblPlaceHoldaer]; 

y ocultarlo en el método TextViewdidChange .

Esta es la manera simple y fácil.

Si alguien necesita una solución para Swift:

Agrega UITextViewDelegate a tu clase

 var placeHolderText = "Placeholder Text..." override func viewDidLoad() { super.viewDidLoad() textView.delegate = self } func textViewShouldBeginEditing(textView: UITextView) -> Bool { self.textView.textColor = .black if(self.textView.text == placeHolderText) { self.textView.text = "" } return true } func textViewDidEndEditing(textView: UITextView) { if(textView.text == "") { self.textView.text = placeHolderText self.textView.textColor = .lightGray } } override func viewWillAppear(animated: Bool) { if(currentQuestion.answerDisplayValue == "") { self.textView.text = placeHolderText self.textView.textColor = .lightGray } else { self.textView.text = "xxx" // load default text / or stored self.textView.textColor = .black } } 

Solución simple Swift 3

Agrega UITextViewDelegate a tu clase

Establece yourTextView.delegate = self

Cree placeholderLabel y yourTextView dentro de yourTextView

Ahora solo anima placeholderLabel.alpha en textViewDidChange :

  func textViewDidChange(_ textView: UITextView) { let newAlpha = textView.text.isEmpty ? 1.0 : 0.0 if placeholderLabel.alpha != newAlpha { UIView.animate(withDuration: 0.3) { self.placeholderLabel.alpha = newAlpha } } } 

es posible que tenga que jugar con la placeholderLabel para configurarlo correctamente, pero eso no debería ser demasiado difícil

Extendí la respuesta de KmKndy, de modo que el marcador de posición permanezca visible hasta que el usuario comience a editar el UITextView lugar de solo UITextView . Esto refleja la funcionalidad en las aplicaciones de Twitter y Facebook. ¡Mi solución no requiere subclases y funciona si el usuario teclea directamente o pega texto!

Ejemplo de PlaceholderAplicación de Twitter

 - (void)textViewDidChangeSelection:(UITextView *)textView{ if ([textView.text isEqualToString:@"What's happening?"] && [textView.textColor isEqual:[UIColor lightGrayColor]])[textView setSelectedRange:NSMakeRange(0, 0)]; } - (void)textViewDidBeginEditing:(UITextView *)textView{ [textView setSelectedRange:NSMakeRange(0, 0)]; } - (void)textViewDidChange:(UITextView *)textView { if (textView.text.length != 0 && [[textView.text substringFromIndex:1] isEqualToString:@"What's happening?"] && [textView.textColor isEqual:[UIColor lightGrayColor]]){ textView.text = [textView.text substringToIndex:1]; textView.textColor = [UIColor blackColor]; //optional } else if(textView.text.length == 0){ textView.text = @"What's happening?"; textView.textColor = [UIColor lightGrayColor]; [textView setSelectedRange:NSMakeRange(0, 0)]; } } - (void)textViewDidEndEditing:(UITextView *)textView { if ([textView.text isEqualToString:@""]) { textView.text = @"What's happening?"; textView.textColor = [UIColor lightGrayColor]; //optional } [textView resignFirstResponder]; } - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{ if (textView.text.length > 1 && [textView.text isEqualToString:@"What's happening?"]) { textView.text = @""; textView.textColor = [UIColor blackColor]; } return YES; } 

solo recuerde configurar myUITextView con el texto exacto en la creación, por ejemplo

 UITextView *myUITextView = [[UITextView alloc] init]; myUITextView.delegate = self; myUITextView.text = @"What's happening?"; myUITextView.textColor = [UIColor lightGrayColor]; //optional 

y hacer que la clase padre sea un delegado UITextView antes de incluir estos métodos, por ejemplo

 @interface MyClass ()  @end 

Recomiendo usar SZTextView .

https://github.com/glaszig/SZTextView

Agregue su UITextView predeterminado del storyboard y luego cambie su clase personalizada a SZTextView como se SZTextView a continuación 👇👇👇👇

enter image description here

Luego verá dos nuevas opciones en el Attribute Inspector 👇👇👇👇

enter image description here

así es como lo hice:

UITextView2.h

 #import  @interface UITextView2 : UITextView  { NSString *placeholder; UIColor *placeholderColor; } @property(nonatomic, retain) NSString *placeholder; @property(nonatomic, retain) UIColor *placeholderColor; -(void)textChanged:(NSNotification*)notif; @end 

UITextView2.m

 @implementation UITextView2 @synthesize placeholder, placeholderColor; - (id)initWithFrame:(CGRect)frame { if (self = [super initWithFrame:frame]) { [self setPlaceholder:@""]; [self setPlaceholderColor:[UIColor lightGrayColor]]; [[NSNotificationCenter defaultCenter] addObserver:self selector:@selector(textChanged:) name:UITextViewTextDidChangeNotification object:nil]; } return self; } -(void)textChanged:(NSNotification*)notif { if ([[self placeholder] length]==0) return; if ([[self text] length]==0) { [[self viewWithTag:999] setAlpha:1]; } else { [[self viewWithTag:999] setAlpha:0]; } } - (void)drawRect:(CGRect)rect { if ([[self placeholder] length]>0) { UILabel *l = [[UILabel alloc] initWithFrame:CGRectMake(8, 8, 0, 0)]; [l setFont:self.font]; [l setTextColor:self.placeholderColor]; [l setText:self.placeholder]; [l setAlpha:0]; [l setTag:999]; [self addSubview:l]; [l sizeToFit]; [self sendSubviewToBack:l]; [l release]; } if ([[self text] length]==0 && [[self placeholder] length]>0) { [[self viewWithTag:999] setAlpha:1]; } [super drawRect:rect]; } - (void)dealloc { [[NSNotificationCenter defaultCenter] removeObserver:self]; [super dealloc]; } @end 

Esta es una solución mucho más sencilla que se comporta exactamente como el marcador de posición de UITextField pero no requiere el diseño de vistas personalizadas o la renuncia del primer respondedor.

 - (void) textViewDidChange:(UITextView *)textView{ if (textView.text.length == 0){ textView.textColor = [UIColor lightGrayColor]; textView.text = placeholderText; [textView setSelectedRange:NSMakeRange(0, 0)]; isPlaceholder = YES; } else if (isPlaceholder && ![textView.text isEqualToString:placeholderText]) { textView.text = [textView.text substringToIndex:1]; textView.textColor = [UIColor blackColor]; isPlaceholder = NO; } } 

(el segundo control en la statement else if es para el caso donde no se ingresa nada y el usuario presiona la tecla de retroceso)

Simplemente configure su clase como UITextViewDelegate. En viewDidLoad debes inicializar como

 - (void) viewDidLoad{ // initialize placeholder text placeholderText = @"some placeholder"; isPlaceholder = YES; self.someTextView.text = placeholderText; self.someTextView.textColor = [UIColor lightGrayColor]; [self.someTextView setSelectedRange:NSMakeRange(0, 0)]; // assign UITextViewDelegate self.someTextView.delegate = self; } 

A continuación se muestra un puerto Swift del código ObjC “SAMTextView” publicado como una de las primeras respuestas a la pregunta. Lo probé en iOS 8. Realicé algunas modificaciones, incluida la compensación de límites para la ubicación del texto del marcador de posición, ya que el original era demasiado alto y muy correcto (sugerencia utilizada en uno de los comentarios a esa publicación).

Sé que hay muchas soluciones simples, pero me gusta el enfoque de la subclasificación de UITextView porque es reutilizable y no tengo que saturar las clases que lo utilizan con los mecanismos.

Swift 2.2:

 import UIKit class PlaceholderTextView: UITextView { @IBInspectable var placeholderColor: UIColor = UIColor.lightGrayColor() @IBInspectable var placeholderText: String = "" override var font: UIFont? { didSet { setNeedsDisplay() } } override var contentInset: UIEdgeInsets { didSet { setNeedsDisplay() } } override var textAlignment: NSTextAlignment { didSet { setNeedsDisplay() } } override var text: String? { didSet { setNeedsDisplay() } } override var attributedText: NSAttributedString? { didSet { setNeedsDisplay() } } required init?(coder aDecoder: NSCoder) { super.init(coder: aDecoder) setUp() } override init(frame: CGRect, textContainer: NSTextContainer?) { super.init(frame: frame, textContainer: textContainer) } private func setUp() { NSNotificationCenter.defaultCenter().addObserver(self, selector: #selector(PlaceholderTextView.textChanged(_:)), name: UITextViewTextDidChangeNotification, object: self) } func textChanged(notification: NSNotification) { setNeedsDisplay() } func placeholderRectForBounds(bounds: CGRect) -> CGRect { var x = contentInset.left + 4.0 var y = contentInset.top + 9.0 let w = frame.size.width - contentInset.left - contentInset.right - 16.0 let h = frame.size.height - contentInset.top - contentInset.bottom - 16.0 if let style = self.typingAttributes[NSParagraphStyleAttributeName] as? NSParagraphStyle { x += style.headIndent y += style.firstLineHeadIndent } return CGRect(x: x, y: y, width: w, height: h) } override func drawRect(rect: CGRect) { if text!.isEmpty && !placeholderText.isEmpty { let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.alignment = textAlignment let attributes: [ String: AnyObject ] = [ NSFontAttributeName : font!, NSForegroundColorAttributeName : placeholderColor, NSParagraphStyleAttributeName : paragraphStyle] placeholderText.drawInRect(placeholderRectForBounds(bounds), withAttributes: attributes) } super.drawRect(rect) } } 

Perdón por agregar otra respuesta, pero acabo de sacar algo así y esto creó el tipo de marcador de posición más cercano a UITextField.

Espero que esto ayude a alguien.

 -(void)textViewDidChange:(UITextView *)textView{ if(textView.textColor == [UIColor lightGrayColor]){ textView.textColor = [UIColor blackColor]; // look at the comment section in this answer textView.text = [textView.text substringToIndex: 0];// look at the comment section in this answer }else if(textView.text.length == 0){ textView.text = @"This is some placeholder text."; textView.textColor = [UIColor lightGrayColor]; textView.selectedRange = NSMakeRange(0, 0); } } -(void)textViewDidChangeSelection:(UITextView *)textView{ if(textView.textColor == [UIColor lightGrayColor] && (textView.selectedRange.location != 0 || textView.selectedRange.length != 0)){ textView.selectedRange = NSMakeRange(0, 0); } } 

Hola, puedes usar IQTextView disponible en IQKeyboard Manager. Es simple de usar e integrar simplemente establece la clase de tu vista de texto en IQTextView y puedes utilizar su propiedad para establecer la etiqueta de marcador de posición con el color que deseas. Puede descargar la biblioteca de IQKeyboardManager

o puedes instalarlo desde cocoapods.

Manera simple de usar esto dentro de alguna línea de código:

Lleve una etiqueta hasta UITextView en .nib conectando esta etiqueta a su código, después de esto.

 - (BOOL)textView:(UITextView *)textView shouldChangeTextInRange:(NSRange)range replacementText:(NSString *)text{ if (range.location>0 || text.length!=0) { placeholderLabel1.hidden = YES; }else{ placeholderLabel1.hidden = NO; } return YES; } 

Modifiqué la implementación de Sam Soffes para que funcione con iOS7:

 - (void)drawRect:(CGRect)rect { [super drawRect:rect]; if (_shouldDrawPlaceholder) { UIEdgeInsets insets = self.textContainerInset; CGRect placeholderRect = CGRectMake( insets.left + self.textContainer.lineFragmentPadding, insets.top, self.frame.size.width - insets.left - insets.right, self.frame.size.height - insets.top - insets.bottom); [_placeholderText drawWithRect:placeholderRect options:NSStringDrawingUsesLineFragmentOrigin | NSStringDrawingTruncatesLastVisibleLine attributes:self.placeholderAttributes context:nil]; } } - (NSDictionary *)placeholderAttributes { if (_placeholderAttributes == nil) { _placeholderAttributes = @ { NSFontAttributeName : self.font, NSForegroundColorAttributeName : self.placeholderColor }; } return _placeholderAttributes; } 

Recuerde establecer _placeholderAttribues = nil en métodos que puedan cambiar la fuente y otros elementos que puedan afectarlos. También es posible que desee omitir la creación “vaga” del diccionario de atributos si eso no le molesta.

EDITAR:

Recuerde llamar a setNeedsDisplay en una versión anulada de setBounds si desea que el marcador de posición se vea bien después de las animaciones de autodiseño y similares.

También podría crear una nueva clase TextViewWithPlaceholder como una subclase de UITextView.

(Este código es bastante difícil, pero creo que está en el camino correcto).

 @interface TextViewWithPlaceholder : UITextView { NSString *placeholderText; // make a property UIColor *placeholderColor; // make a property UIColor *normalTextColor; // cache text color here whenever you switch to the placeholderColor } - (void) setTextColor: (UIColor*) color { normalTextColor = color; [super setTextColor: color]; } - (void) updateForTextChange { if ([self.text length] == 0) { normalTextColor = self.textColor; self.textColor = placeholderColor; self.text = placeholderText; } else { self.textColor = normalTextColor; } } 

En tu delegado, agrega esto:

 - (void)textViewDidChange:(UITextView *)textView { if ([textView respondsToSelector: @selector(updateForTextChange)]) { [textView updateForTextChange]; } } 

I made my own version of the subclass of ‘UITextView’. I liked Sam Soffes ‘s idea of using the notifications, but I didn’t liked the drawRect: overwrite. Seems overkill to me. I think I made a very clean implementation.

You can look at my subclass here . A demo project is also included.

This thread has had plenty of answers, but here’s the version I prefer.

It extends the existing UITextView class so is easily reuseable, and it doesn’t intercept the events like textViewDidChange (which might break user’s code, if they were already intercepting these events elsewhere).

Using my code (shown below), you can easily add a placeholder to any of your UITextViews like this:

 self.textViewComments.placeholder = @"(Enter some comments here.)"; 

When you set this new placeholder value, it quietly adds a UILabel on top of your UITextView , then hide/shows it as necessary:

enter image description here

Okay, to make these changes, add a “UITextViewHelper.h” file containing this code:

 // UITextViewHelper.h // Created by Michael Gledhill on 13/02/15. #import  @interface UITextView (UITextViewHelper) @property (nonatomic, strong) NSString* placeholder; @property (nonatomic, strong) UILabel* placeholderLabel; @property (nonatomic, strong) NSString* textValue; -(void)checkIfNeedToDisplayPlaceholder; @end 

…and a UITextViewHelper.m file containing this:

 // UITextViewHelper.m // Created by Michael Gledhill on 13/02/15. // // This UITextView category allows us to easily display a PlaceHolder string in our UITextView. // The downside is that, your code needs to set the "textValue" rather than the "text" value to safely set the UITextView's text. // #import "UITextViewHelper.h" #import  @implementation UITextView (UITextViewHelper) #define UI_PLACEHOLDER_TEXT_COLOR [UIColor colorWithRed:170.0/255.0 green:170.0/255.0 blue:170.0/255.0 alpha:1.0] @dynamic placeholder; @dynamic placeholderLabel; @dynamic textValue; -(void)setTextValue:(NSString *)textValue { // Change the text of our UITextView, and check whether we need to display the placeholder. self.text = textValue; [self checkIfNeedToDisplayPlaceholder]; } -(NSString*)textValue { return self.text; } -(void)checkIfNeedToDisplayPlaceholder { // If our UITextView is empty, display our Placeholder label (if we have one) if (self.placeholderLabel == nil) return; self.placeholderLabel.hidden = (![self.text isEqualToString:@""]); } -(void)onTap { // When the user taps in our UITextView, we'll see if we need to remove the placeholder text. [self checkIfNeedToDisplayPlaceholder]; // Make the onscreen keyboard appear. [self becomeFirstResponder]; } -(void)keyPressed:(NSNotification*)notification { // The user has just typed a character in our UITextView (or pressed the delete key). // Do we need to display our Placeholder label ? [self checkIfNeedToDisplayPlaceholder]; } #pragma mark - Add a "placeHolder" string to the UITextView class NSString const *kKeyPlaceHolder = @"kKeyPlaceHolder"; -(void)setPlaceholder:(NSString *)_placeholder { // Sets our "placeholder" text string, creates a new UILabel to contain it, and modifies our UITextView to cope with // showing/hiding the UILabel when needed. objc_setAssociatedObject(self, &kKeyPlaceHolder, (id)_placeholder, OBJC_ASSOCIATION_RETAIN_NONATOMIC); self.placeholderLabel = [[UILabel alloc] initWithFrame:self.frame]; self.placeholderLabel.numberOfLines = 1; self.placeholderLabel.text = _placeholder; self.placeholderLabel.textColor = UI_PLACEHOLDER_TEXT_COLOR; self.placeholderLabel.backgroundColor = [UIColor clearColor]; self.placeholderLabel.userInteractionEnabled = true; self.placeholderLabel.font = self.font; [self addSubview:self.placeholderLabel]; [self.placeholderLabel sizeToFit]; // Whenever the user taps within the UITextView, we'll give the textview the focus, and hide the placeholder if necessary. [self addGestureRecognizer:[[UITapGestureRecognizer alloc] initWithTarget:self action:@selector(onTap)]]; // Whenever the user types something in the UITextView, we'll see if we need to hide/show the placeholder label. [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil]; [self checkIfNeedToDisplayPlaceholder]; } -(NSString*)placeholder { // Returns our "placeholder" text string return objc_getAssociatedObject(self, &kKeyPlaceHolder); } #pragma mark - Add a "UILabel" to this UITextView class NSString const *kKeyLabel = @"kKeyLabel"; -(void)setPlaceholderLabel:(UILabel *)placeholderLabel { // Stores our new UILabel (which contains our placeholder string) objc_setAssociatedObject(self, &kKeyLabel, (id)placeholderLabel, OBJC_ASSOCIATION_RETAIN_NONATOMIC); [[NSNotificationCenter defaultCenter] addObserver:self selector: @selector(keyPressed:) name:UITextViewTextDidChangeNotification object:nil]; [self checkIfNeedToDisplayPlaceholder]; } -(UILabel*)placeholderLabel { // Returns our new UILabel return objc_getAssociatedObject(self, &kKeyLabel); } @end 

Yup, it’s a lot of code, but once you’ve added it to your project and included the .h file…

 #import "UITextViewHelper.h" 

…you can easily use placeholders in UITextViews .

There’s one gotcha though.

Si haces esto:

 self.textViewComments.placeholder = @"(Enter some comments here.)"; self.textViewComments.text = @"Ooooh, hello there"; 

…the placeholder will appear on top of the text. When you set the text value, none of the regular notifications gets called, so I couldn’t work out how to call my function to decide whether to show/hide the placeholder.

The solution is to set the textValue rather than text :

 self.textViewComments.placeholder = @"(Enter some comments here.)"; self.textViewComments.textValue = @"Ooooh, hello there"; 

Alternatively, you can set the text value, then call checkIfNeedToDisplayPlaceholder .

 self.textViewComments.text = @"Ooooh, hello there"; [self.textViewComments checkIfNeedToDisplayPlaceholder]; 

I like solutions like this, as they “fill the gap” between what Apple provides us with, and what we (as developers) actually need in our apps. You write this code once, add it to your library of “helper” .m/.h files, and, over time, the SDK actually starts becoming less frustrating.

(I wrote a similar helper for adding a “clear” button to my UITextViews, another thing which annoyingly exists in UITextField but not in UITextView …)

First take a label in .h file.

Here I take

 UILabel * lbl; 

Then in .m under viewDidLoad declare it

 lbl = [[UILabel alloc] initWithFrame:CGRectMake(8.0, 0.0,250, 34.0)]; lbl.font=[UIFont systemFontOfSize:14.0]; [lbl setText:@"Write a message..."]; [lbl setBackgroundColor:[UIColor clearColor]]; [lbl setTextColor:[UIColor lightGrayColor]]; [textview addSubview:lbl]; 

textview is my TextView.

Now declare

 -(void)textViewDidChange:(UITextView *)textView { if (![textView hasText]){ lbl.hidden = NO; } else{ lbl.hidden = YES; } } 

And your Textview placeholder is ready !

  - (void)textViewDidChange:(UITextView *)textView { placeholderLabel.hidden = YES; } 

put a label over the textview.

It is not possible to create placeholder in UITextView but you can generate effect like place holder by this.

  - (void)viewDidLoad{ commentTxtView.text = @"Comment"; commentTxtView.textColor = [UIColor lightGrayColor]; commentTxtView.delegate = self; } - (BOOL) textViewShouldBeginEditing:(UITextView *)textView { commentTxtView.text = @""; commentTxtView.textColor = [UIColor blackColor]; return YES; } -(void) textViewDidChange:(UITextView *)textView { if(commentTxtView.text.length == 0){ commentTxtView.textColor = [UIColor lightGrayColor]; commentTxtView.text = @"Comment"; [commentTxtView resignFirstResponder]; } } 

OR you can add label in textview just like

  lbl = [[UILabel alloc] initWithFrame:CGRectMake(10.0, 0.0,textView.frame.size.width - 10.0, 34.0)]; [lbl setText:kDescriptionPlaceholder]; [lbl setBackgroundColor:[UIColor clearColor]]; [lbl setTextColor:[UIColor lightGrayColor]]; textView.delegate = self; [textView addSubview:lbl]; 

and set

 - (void)textViewDidEndEditing:(UITextView *)theTextView { if (![textView hasText]) { lbl.hidden = NO; } } - (void) textViewDidChange:(UITextView *)textView { if(![textView hasText]) { lbl.hidden = NO; } else{ lbl.hidden = YES; } } 

Here’s yet another way to do it, one that reproduces the slight indentation of UITextField ‘s placeholder:

Drag a UITextField right under the UITextView so that their top left corners are aligned. Add your placeholder text to the text field.

In viewDidLoad, add:

 [tView setDelegate:self]; tView.contentInset = UIEdgeInsetsMake(-8,-8,0,0); tView.backgroundColor = [UIColor clearColor]; 

Then add:

 - (void)textViewDidChange:(UITextView *)textView { if (textView.text.length == 0) { textView.backgroundColor = [UIColor clearColor]; } else { textView.backgroundColor = [UIColor whiteColor]; } } 

Lets make it easy

Create one UILabel and place it on your text view(Give the text as Placeholder-set color gray-you can do all this in your xib) Now in you header file declare the UILabel and also the the textviewDelegate Now you can simply hide the label when you click on the textview

complete code below

encabezamiento

 @interface ViewController :UIViewController{ } @property (nonatomic,strong) IBOutlet UILabel *PlceHolder_label; @property (nonatomic,strong) IBOutlet UITextView *TextView; @end 

implementación

 @implementation UploadFoodImageViewController @synthesize PlceHolder_label,TextView; - (void)viewDidLoad { [super viewDidLoad]; } - (BOOL)textViewShouldBeginEditing:(UITextView *)textView{ if([textView isEqual:TextView]){ [PlceHolder_label setHidden:YES]; [self.tabScrlVw setContentOffset:CGPointMake(0,150) animated:YES]; } return YES; } 

@end

Dont forget to connect the textView and UILabel to filesowner from xib

Take a look at UTPlaceholderTextView .

This is a convenient subclass of UITextView that supports placeholder similiar to that of UITextField. Main peculiarities:

  • Does not use subviews
  • Does not override drawRect:
  • Placeholder could be of arbitrary length, and rendered just the same way as usual text

I read through all of these, but came up with a very short, Swift 3, solution that has worked in all of my tests. It could stand a little more generality, but the process is simple. Here’s the entire thing which I call “TextViewWithPlaceholder”.

 import UIKit class TextViewWithPlaceholder: UITextView { public var placeholder: String? public var placeholderColor = UIColor.lightGray private var placeholderLabel: UILabel? // Set up notification listener when created from a XIB or storyboard. // You can also set up init() functions if you plan on creating // these programmatically. override func awakeFromNib() { super.awakeFromNib() NotificationCenter.default.addObserver(self, selector: #selector(TextViewWithPlaceholder.textDidChangeHandler(notification:)), name: .UITextViewTextDidChange, object: self) placeholderLabel = UILabel() placeholderLabel?.alpha = 0.85 placeholderLabel?.textColor = placeholderColor } // By using layoutSubviews, you can size and position the placeholder // more accurately. I chose to hard-code the size of the placeholder // but you can combine this with other techniques shown in previous replies. override func layoutSubviews() { super.layoutSubviews() placeholderLabel?.textColor = placeholderColor placeholderLabel?.text = placeholder placeholderLabel?.frame = CGRect(x: 6, y: 4, width: self.bounds.size.width-16, height: 24) if text.isEmpty { addSubview(placeholderLabel!) bringSubview(toFront: placeholderLabel!) } else { placeholderLabel?.removeFromSuperview() } } // Whenever the text changes, just trigger a new layout pass. func textDidChangeHandler(notification: Notification) { layoutSubviews() } } 

This mimics UITextField’s placeholder perfectly, where the place holder text stays until you actually type something.

 private let placeholder = "Type here" @IBOutlet weak var textView: UITextView! { didSet { textView.textColor = UIColor.lightGray textView.text = placeholder textView.selectedRange = NSRange(location: 0, length: 0) } } extension ViewController: UITextViewDelegate { func textViewDidChangeSelection(_ textView: UITextView) { // Move cursor to beginning on first tap if textView.text == placeholder { textView.selectedRange = NSRange(location: 0, length: 0) } } func textView(_ textView: UITextView, shouldChangeTextIn range: NSRange, replacementText text: String) -> Bool { if textView.text == placeholder && !text.isEmpty { textView.text = nil textView.textColor = UIColor.black textView.selectedRange = NSRange(location: 0, length: 0) } return true } func textViewDidChange(_ textView: UITextView) { if textView.text.isEmpty { textView.textColor = UIColor.lightGray textView.text = placeholder } } } 

I recommend use pod ‘UITextView+Placeholder’

 pod 'UITextView+Placeholder' 

on your code

 #import "UITextView+Placeholder.h" //// UITextView *textView = [[UITextView alloc] init]; textView.placeholder = @"How are you?"; textView.placeholderColor = [UIColor lightGrayColor]; 

How to insert placeholder in UITextView?

The answer of PJR works like a charm. The ones here didn’t work for me. Maybe an iOS5 thing.