O estilo UITextView está sendo redefinido após definir a propriedade de texto


145

Eu tenho UITextView *_masterTexte depois da setTextfonte da propriedade do método de chamada está sendo redefinida. Está acontecendo depois que eu mudo o sdk 7. _masterText é IBOutlet, global e propriedades são definidas no storyboard. Sou só eu ou isso é bug geral do SDK?

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

@implementation myViewController

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

Respostas:


450

Sentado com isso por horas, encontrei o bug. Se a propriedade "Selecionável" = NÃO, ela redefinirá a fonte e a cor da fonte quando setText for usado.

Portanto, ative Selecionável e o bug se foi.


15
Isso acontece comigo também no Xcode 5. Minha solução alternativa é definir temporariamente selecionável = YES antes de chamar setText:
Rollin_s 7/13

8
Uau, que bug ridículo. Obrigado pela compreensão!
Micah

3
Obrigado MUITO MUITO!
Magurizio 22/03

6
6.4 ainda tem esse problema
RndmTsk

4
Isso parece ter sido corrigido no iOS 10, se você ainda tiver como alvo o iOS 9 ou abaixo, precisará fazer a solução alternativa.
user1184205

11

Encontrei o mesmo problema (no Xcode 6.1) e, embora a resposta de John Cogan funcionasse para mim, descobri que estender a classe UITextView com uma categoria era uma solução melhor para o meu projeto em particular.

interface

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

implementação

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

1
E rapidamente:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }
little

8

Se você deseja que sua exibição de texto seja "somente leitura", marque Editável e Selecionável e desmarque a opção Interação do usuário ativada. Com isso, o UITextView estava se comportando como eu queria

insira a descrição da imagem aqui

insira a descrição da imagem aqui


3
Parece, na superfície, uma solução viável, mas, em última análise, não é uma boa opção para um UITextView. Normalmente você escolhe um UITextView porque precisa de uma área de texto rolável. desativar a interação do usuário também desativa a exibição de rolagem. Para mim, a escolha de usar um UITextView foi porque eu tinha uma área que precisava conter mais texto do que caberia nessa área e ser capaz de rolar.
Jhelzer #

6

Esse problema e a resposta acima ajudaram, mas eu adicionei um invólucro ao meu código ViewController da seguinte maneira e passe a instância e o texto do uiview para alterar e a função do invólucro alterna o valor Selecionável, altera o texto e o desliga novamente. Útil quando você precisa que o uitextview esteja sempre desativado por padrão.

/*
    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
Poderia ser melhor a subclasse UITextView e override setText e usar sua subclasse no aplicativo
powerj1984

2

EDIT:

A configuração da fonte para o UITextView no iOS 7 funcionará para mim, se primeiro você definir o texto e depois definir a fonte:

@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

}

Em um arquivo XIB, se você adicionar algum texto ao seu UITextView e alterar a fonte ou a cor, ele funcionará.


hmm .. Eu uso propriedade, mas nenhuma mudança.
27413

esqueci [super viewWillAppear: animado];
Jordan Montel

Esqueci-me disso, mas isso não afetou :( #
21713 Błażej

limpa e reiniciar o XCode porque é bem trabalho para mim sem a linha "_myTextView.font ..." mesmo se eu mudar a fonte do arquivo XIB
Jordan Montel

Limpe, reinicie e sem efeito. Projeto> Destino de implantação iOS 7.0, SDK base 7.0 no destino nas mesmas configurações.
27413

2

Aqui está uma solução rápida de subclasse que costumo usar para esse 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

Esse problema ressurgiu no Xcode 8. Foi assim que eu o corrigi:

A extensão foi alterada para:

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

e verificou a opção Selecionável no Interface Builder.

Não é muito elegante ter esse parâmetro 'selecionável', mas serve.


1

No iOS 8.3, a solução alternativa da configuração "selecionável" para SIM antes do setText e NÃO depois, não a corrigiu.

Descobri que também era necessário definir "selecionável" como YES no storyboard antes que isso funcionasse.


Você salvou meu dia, eu acredito que este é apenas mais um erro ridículo em CocoaTouch
Chris

1

Isso funcionou para mim:

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

0

Para mim, com texto atribuído, eu só precisava definir a fonte no dicionário de atributos, em vez de defini-la em seu próprio campo.


0

Estou tendo esse problema para. Uma solução rápida e amigável da resposta de @Ken Steele. Estendo o UITextView e adiciono uma propriedade computada.

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 que ajude.


0

Já faz 3 anos e o bug ainda existe na versão estável mais recente do Xcode (7.3). Claramente, a Apple não irá corrigi-lo tão cedo, deixando aos desenvolvedores duas opções: deixar selecionável ativado e definir UserInteractionEnabled como false ou swizzling de método.

Se você tiver um botão no seu textView, o primeiro não será suficiente.

Solução sem necessidade de alteração de código no 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
        }
    }
}

Objetivo-C:

#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

Usando a solução alternativa discutida neste problema, esta extensão ao UITextView fornece uma setTextInCurrentStyle()função. Baseado na solução de Alessandro Ranaldi, mas não requer que o atual valor isSelectable seja passado para a função.

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
Ao utilizar nosso site, você reconhece que leu e compreendeu nossa Política de Cookies e nossa Política de Privacidade.
Licensed under cc by-sa 3.0 with attribution required.