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"];
}
Błażej
fuente

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á.

Bosse Nilsson
fuente
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
Ken Steele
fuente
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í

Chuy47
fuente
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];
    }
}
John Cogan
fuente
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á.

Jordan Montel
fuente
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
        }
    }
}
WaltersGE1
fuente
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á.

Alessandro Ranaldi
fuente
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.

Peter Johnson
fuente
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
David Green
fuente
0

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

bocaza
fuente
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.

Última jugada
fuente
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
Mark Bourke
fuente
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
    }
}
Duncan Babbage
fuente