web-dev-qa-db-fra.com

Le style UITextView est en cours de réinitialisation après la définition de la propriété text

J'ai UITextView *_masterText et après la méthode d'appel setText, la police de la propriété est en cours de réinitialisation. Cela se produit après que j'ai changé de sdk 7. _masterText est IBOutlet, global et les propriétés sont définies dans le storyboard. C'est seulement moi ou c'est un bogue général du SDK?

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

@implementation myViewController

-(void)viewWillAppear:(BOOL)animated
{
    [_masterText setText:@"New text"];
}
145
Błażej

Assis avec cela pendant des heures, j'ai trouvé le bogue. Si la propriété "Selectable" = NO, la police et la police de caractères sont réinitialisées lorsque setText est utilisé.

Alors activez Selectable sur ON et le bogue aura disparu.

450
Bosse Nilsson

J'ai rencontré le même problème (sur Xcode 6.1) et alors que réponse de John Cogan a fonctionné pour moi, j'ai constaté qu'étendre la classe UITextView avec une catégorie était une meilleure solution pour mon projet particulier.

interface

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

la mise en oeuvre

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

Si vous voulez que votre vue texte soit en "lecture seule", vous pouvez cocher Modifiable et Sélectable et désélectionner Interaction utilisateur activée, avec ceci, UITextView se comportait comme je le souhaitais.

enter image description here

enter image description here

8
Chuy47

Si ce problème m'avait aidé et que la réponse ci-dessus avait été utile, j'ai ajouté un wrapper à mon code ViewController comme suit, en passant juste l'instance uiview et le texte à modifier. La fonction wrapper active/désactive la valeur Selectable, modifie le texte puis le désactive. Utile lorsque vous avez besoin que la propriété uitextview soit désactivée à tout moment par défaut.

/*
    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];
    }
}
6
John Cogan

Ce problème a refait surface dans Xcode 8. Voici comment je l'ai corrigé:

Modification de l'extension en:

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

et coché l'option Sélectionnable dans le Générateur d'interface.

Ce n'est pas très élégant d'avoir ce paramètre 'sélectionnable' mais ça ira.

2
Alessandro Ranaldi

EDIT:

La définition de la police pour UITextView dans iOS 7 fonctionne pour moi si vous définissez tout d'abord le texte, puis la police:

@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

}

Sur un fichier XIB, si vous ajoutez du texte dans votre UITextView et modifiez la police ou la couleur, cela fonctionnera.

2
Jordan Montel

Voici une solution rapide de sous-classe que j'utilise souvent pour résoudre ce problème.

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
WaltersGE1

Dans iOS 8.3, la solution de contournement consistant à définir "sélectionnable" sur OUI avant le setText et sur NO après ne résolvait pas le problème pour moi.

J'ai découvert que je devais également définir "sélectionnable" sur OUI dans le scénarimage avant que cela ne fonctionne.

1
Peter Johnson

Cela a fonctionné pour moi:

let font = textView.font
textView.attributedText = attributedString
textView.font  = font
1
David Green

Pour moi avec un texte attribué, je devais simplement définir la police dans le dictionnaire des attributs plutôt que de la définir dans son propre champ.

0
loudmouth

J'ai ce problème à. Une solution rapide de la réponse de @Ken Steele. J'étends UITextView et ajoute une propriété calculée.

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

j'espère que ça aide.

0
LastMove

Cela fait 3 ans et le bogue existe toujours dans la dernière version stable de Xcode (7.3). Clairement, Apple ne le réglera pas bientôt, laissant deux options aux développeurs: laisser sélectionnable et activer UserInteractionEnabled sur false ou Method swizzling.

Si vous avez un bouton sur votre textView, le premier ne suffira pas.

Solution sans changement de code dans 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
        }
    }
}

Objectif 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
Mark Bourke

À l'aide de la solution de contournement décrite dans ce numéro, cette extension de UITextView fournit une fonction setTextInCurrentStyle(). D'après la solution d'Alessandro Ranaldi, mais ne nécessite pas que la valeur isSelectable actuelle soit transmise à la fonction.

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
0
Duncan Babbage