El estilo UITextView se restablece después de configurar la propiedad de texto


145

Tengo UITextView *_masterTexty después de la llamada, la setTextpropiedad del método se restablece la fuente. Está sucediendo después de cambiar el SDK 7. _masterText es IBOutletglobal y las propiedades se configuran en el guión gráfico. ¿Soy solo yo o este es un error general del SDK?

@interface myViewController : UIViewController
{
  IBOutlet UITextView *_masterText;
}

@implementation myViewController

-(void)viewWillAppear:(BOOL)animated
{
    [_masterText setText:@"New text"];
}

Respuestas:


450

Sentado con esto durante horas, encontré el error. Si la propiedad "Seleccionable" = NO restablecerá la fuente y el color de fuente cuando se use setText.

Así que encienda el seleccionable y el error desaparecerá.


15
Esto también me sucede a mí en Xcode 5. Mi solución es establecer temporalmente seleccionable = YES antes de llamar a setText:
Rollin_s

8
Wow, qué bicho ridículo. Gracias por la idea!
Micah

3
Muchas muchas gracias !
Magurizio

66
6.4 todavía tiene este problema
RndmTsk

44
Esto parece estar solucionado en iOS 10, si todavía está apuntando a iOS 9 o inferior, deberá hacer la solución.
user1184205

11

Me encontré con el mismo problema (en Xcode 6.1) y aunque la respuesta de John Cogan funcionó para mí, descubrí que extender la clase UITextView con una categoría era una mejor solución para mi proyecto en particular.

interfaz

@interface UITextView (XcodeSetTextFormattingBugWorkaround)
    - (void)setSafeText:(NSString *)textValue;
@end

implementación

@implementation UITextView (XcodeSetTextFormattingBugWorkaround)
- (void)setSafeText:(NSString *)textValue
{
    BOOL selectable = [self isSelectable];
    [self setSelectable:YES];
    [self setText:textValue];
    [self setSelectable:selectable];
}
@end

1
Y en rápida:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }
poco

8

Si desea que su vista de texto sea de "solo lectura", puede marcar Editable y Seleccionable y desmarcar Interacción del usuario habilitada, con esto UITextView se comportó como yo quería

ingrese la descripción de la imagen aquí

ingrese la descripción de la imagen aquí


3
En la superficie, parece ser una solución viable, pero finalmente no es una buena opción para un UITextView. Normalmente elige un UITextView porque necesita un área de texto desplazable. deshabilitar la interacción del usuario también deshabilita la vista de desplazamiento. Para mí, la elección de usar un UITextView fue porque tenía un área que necesitaba contener más texto del que cabía en esa área y poder desplazarme.
jhelzer

6

Tuve este problema y la respuesta anterior me ayudó, pero agregué un contenedor a mi código ViewController de la siguiente manera y simplemente pasé la instancia uiview y el texto para cambiar y la función de contenedor activa el valor Seleccionable, cambia el texto y luego lo apaga nuevamente. Útil cuando necesita que uitextview esté desactivado en todo momento de forma predeterminada.

/*
    We set the text views Selectable value to YES temporarily, change text and turn it off again.
    This is a known bug that if the selectable value = NO the view loses its formatting.
 */
-(void)changeTextOfUiTextViewAndKeepFormatting:(UITextView*)viewToUpdate withText:(NSString*)textValue
{
    if(![viewToUpdate isSelectable]){
        [viewToUpdate setSelectable:YES];
        [viewToUpdate setText:textValue];
        [viewToUpdate setSelectable:NO];
    }else{
        [viewToUpdate setText:textValue];
        [viewToUpdate setSelectable:NO];
    }
}

1
Podría ser mejor subclasificar UITextView y anular setText y usar su subclase en la aplicación
powerj1984

2

EDITAR:

Configurar la fuente para UITextView en iOS 7 funciona para mí si primero establece el texto y luego establece la fuente:

@property (nonatomic, weak) IBOutlet UITextView *masterText;

@implementation myViewController

-(void)viewWillAppear:(BOOL)animated
{
    [super viewWillAppear:animated];

    _myTextView.text = @"My Text";

    _myTextView.font = [UIFont fontWithName:@"Helvetica.ttf" size:16]; // Set Font

}

En un archivo XIB, si agrega texto en su UITextView y cambia la fuente o el color, funcionará.


hmm .. uso propiedad pero no cambio.
Błażej

olvidé [super viewWillAppear: animada];
Jordan Montel

Lo olvidé, pero eso no afectó :(
Błażej

limpiar y reiniciar su XCode porque funciona bien para mí sin la línea "_myTextView.font ..." incluso si cambio la fuente del archivo XIB
Jordan Montel

Limpio, reinicio y sin efecto. Proyecto> iOS Deployment Target 7.0, Base SDK 7.0 en target la misma configuración.
Błażej

2

Aquí hay una solución rápida de subclase que uso a menudo para este problema.

class WorkaroundTextView: UITextView {
    override var text: String! {
        get {
            return super.text
        }
        set {
            let originalSelectableValue = self.selectable
            self.selectable = true
            super.text = newValue
            self.selectable = originalSelectableValue
        }
    }
}

2

Este problema volvió a aparecer en Xcode 8. Así es como lo solucioné:

Cambió la extensión a:

extension UITextView{
    func setTextAvoidXcodeIssue(newText : String, selectable: Bool){
        isSelectable = true
        text = newText
        isSelectable = selectable
    }
}

y marcó la opción Seleccionable en el Creador de interfaces.

No es muy elegante tener ese parámetro 'seleccionable', pero servirá.


1

En iOS 8.3, la solución alternativa de establecer "seleccionable" en SÍ antes del setText, y NO después, no me lo solucionó.

Descubrí que también necesitaba establecer "seleccionable" en SÍ en el guión gráfico, antes de que esto funcionara.


Me salvaste el día, creo que este es solo otro error ridículo en CocoaTouch
Chris

1

Esto funcionó para mí:

let font = textView.font
textView.attributedText = attributedString
textView.font  = font

0

Para mí con texto atribuido, solo necesitaba configurar la fuente en el diccionario de atributos en lugar de configurarla en su propio campo.


0

Estoy teniendo este problema para. Una solución rápida y amigable de la respuesta de @Ken Steele. Extiendo UITextView y agrego una propiedad calculada.

extension UITextView {
    // For older Swift version output should be NSString!
    public var safeText:String!
        {
        set {
            let selectable = self.selectable;
            self.selectable = true;
            self.text = newValue;
            self.selectable = selectable;
        }
        get {
            return self.text;
        }
    }
}

Espero eso ayude.


0

Han pasado 3 años y el error aún existe en la última versión estable de Xcode (7.3). Claramente, Apple no lo solucionará en el corto plazo, dejando a los desarrolladores con dos opciones: dejar seleccionable y configurar UserInteractionEnabled en falso o Método swizzling.

Si tiene un botón en su textView, el primero no será suficiente.

Solución sin cambio de código requerido en swift:

import UIKit

extension UITextView {
    @nonobjc var text: String! {
        get {
            return performSelector(Selector("text")).takeUnretainedValue() as? String ?? ""
        } set {
            let originalSelectableValue = selectable
            selectable = true
            performSelector(Selector("setText:"), withObject: newValue)
            selectable = originalSelectableValue
        }
    }
}

C objetivo:

#import <objc/runtime.h>
#import <UIKit/UIKit.h>

@implementation UITextView (SetTextFix)

+ (void)load {
    static dispatch_once_t onceToken;
    dispatch_once(&onceToken, ^{
        Class class = [self class];

        SEL originalSelector = @selector(setText:);
        SEL swizzledSelector = @selector(xxx_setText:);

        Method originalMethod = class_getInstanceMethod(class, originalSelector);
        Method swizzledMethod = class_getInstanceMethod(class, swizzledSelector);

        BOOL didAddMethod =
        class_addMethod(class,
                    originalSelector,
                    method_getImplementation(swizzledMethod),
                    method_getTypeEncoding(swizzledMethod));

        if (didAddMethod) {
            class_replaceMethod(class,
                            swizzledSelector,
                            method_getImplementation(originalMethod),
                            method_getTypeEncoding(originalMethod));
        } else {
            method_exchangeImplementations(originalMethod, swizzledMethod);
       }
   });
}

- (void)xxx_setText:(NSString *)text {
    BOOL originalSelectableValue = self.selectable;
    self.selectable = YES;
    [self xxx_setText:text];
    self.selectable = originalSelectableValue;
}

@end

0

Utilizando la solución discutida en este número, esta extensión de UITextView proporciona una setTextInCurrentStyle()función. Basado en la solución de Alessandro Ranaldi, pero no requiere que el valor actual isSelectable se pase a la función.

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
Al usar nuestro sitio, usted reconoce que ha leído y comprende nuestra Política de Cookies y Política de Privacidad.
Licensed under cc by-sa 3.0 with attribution required.