Der UITextView-Stil wird nach dem Festlegen der Texteigenschaft zurückgesetzt

145

Ich habe UITextView *_masterTextund nach dem Aufruf Methode setTextEigenschaft Schriftart wird zurückgesetzt. Es passiert, nachdem ich SDK 7 geändert habe. _MasterText ist IBOutletglobal und die Eigenschaften werden im Storyboard festgelegt. Es ist nur ich oder das ist ein allgemeiner SDK-Fehler?

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

@implementation myViewController

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

Antworten:

450

Ich saß stundenlang damit und fand den Fehler. Wenn die Eigenschaft "Auswählbar" = NEIN ist, werden Schriftart und Schriftfarbe zurückgesetzt, wenn setText verwendet wird.

Schalten Sie also Selectable ein und der Fehler ist verschwunden.

Bosse Nilsson
quelle
15
Dies passiert mir auch in Xcode 5. Meine Problemumgehung besteht darin, vorübergehend selectable = YES zu setzen, bevor setText aufgerufen wird:
Rollin_s
8
Wow, was für ein lächerlicher Fehler. Danke für den Einblick!
Micah
3
Vielen vielen Dank !
Magurizio
6
6.4 hat immer noch dieses Problem
RndmTsk
4
Dies scheint in iOS 10 behoben zu sein. Wenn Sie immer noch auf iOS 9 oder niedriger abzielen, müssen Sie die Problemumgehung durchführen.
user1184205
11

Ich bin auf dasselbe Problem gestoßen (auf Xcode 6.1), und während John Cogans Antwort für mich funktionierte, fand ich, dass die Erweiterung der UITextView-Klasse um eine Kategorie eine bessere Lösung für mein spezielles Projekt war.

Schnittstelle

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

Implementierung

@implementation UITextView (XcodeSetTextFormattingBugWorkaround)
- (void)setSafeText:(NSString *)textValue
{
    BOOL selectable = [self isSelectable];
    [self setSelectable:YES];
    [self setText:textValue];
    [self setSelectable:selectable];
}
@end
Ken Steele
quelle
1
Und in Kürze:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }
kleine
8

Wenn Sie möchten, dass Ihre Textansicht "schreibgeschützt" ist, können Sie "Bearbeitbar" und "Auswählbar" aktivieren und die Option "Benutzerinteraktion aktiviert" deaktivieren. Damit hat sich die UITextView wie gewünscht verhalten

Geben Sie hier die Bildbeschreibung ein

Geben Sie hier die Bildbeschreibung ein

Chuy47
quelle
3
Dies scheint an der Oberfläche eine praktikable Lösung zu sein, ist aber letztendlich keine gute Option für eine UITextView. Normalerweise wählen Sie eine UITextView, da Sie einen scrollbaren Textbereich benötigen. Durch Deaktivieren der Benutzerinteraktion wird auch die Bildlaufansicht deaktiviert. Für mich war die Wahl einer UITextView, weil ich einen Bereich hatte, der mehr Text enthalten musste, als in diesen Bereich passen konnte, und in der Lage war, zu scrollen.
Jhelzer
6

Hatte dieses Problem selbst und die obige Antwort geholfen, aber ich habe meinem ViewController-Code wie folgt einen Wrapper hinzugefügt und einfach die zu ändernde uiview-Instanz und den zu ändernden Text übergeben. Die Wrapper-Funktion schaltet den auswählbaren Wert ein, ändert den Text und schaltet ihn dann wieder aus. Hilfreich, wenn die uitextview standardmäßig immer deaktiviert sein muss.

/*
    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
quelle
1
Könnte besser sein, UITextView zu unterklassifizieren und setText zu überschreiben und Ihre Unterklasse in der App zu verwenden
powerj1984
2

EDIT:

Das Festlegen der Schriftart für UITextView in iOS 7 funktioniert für mich, wenn Sie zuerst den Text und danach die Schriftart festlegen:

@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

}

Wenn Sie in einer XIB-Datei Text in Ihre UITextView einfügen und die Schriftart oder Farbe ändern, funktioniert dies.

Jordan Montel
quelle
hmm .. Ich benutze Eigentum, aber keine Änderung.
Błażej
vergessen [super viewWillAppear: animiert];
Jordan Montel
Ich habe es vergessen, aber das hatte keinen Einfluss auf :(
Błażej
Bereinigen Sie Ihren XCode und starten Sie ihn neu, da er ohne die Zeile "_myTextView.font ..." problemlos funktioniert, auch wenn ich die Schriftart aus der XIB-Datei ändere
Jordan Montel
Reinigen, neu starten und keine Wirkung. Projekt> iOS-Bereitstellungsziel 7.0, Basis-SDK 7.0 im Ziel dieselben Einstellungen.
Błażej
2

Hier ist eine schnelle Unterklassenlösung, die ich häufig für dieses Problem verwende.

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
quelle
2

Dieses Problem ist in Xcode 8 erneut aufgetreten. So habe ich es behoben:

Die Erweiterung wurde geändert in:

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

und aktivierte die Option Auswählbar im Interface Builder.

Es ist nicht sehr elegant, diesen 'auswählbaren' Parameter zu haben, aber es wird reichen.

Alessandro Ranaldi
quelle
1

In iOS 8.3 wurde die Problemumgehung, bei der "auswählbar" vor dem setText auf "JA" und danach auf "NEIN" gesetzt wurde, für mich nicht behoben.

Ich musste im Storyboard auch "auswählbar" auf JA setzen, bevor dies funktionieren würde.

Peter Johnson
quelle
Sie haben meinen Tag gerettet, ich glaube, dies ist nur ein weiterer lächerlicher Fehler in CocoaTouch
Chris
1

Das hat bei mir funktioniert:

let font = textView.font
textView.attributedText = attributedString
textView.font  = font
David Green
quelle
0

Für mich mit zugeordnetem Text musste ich nur die Schriftart im Attributwörterbuch festlegen, anstatt sie in einem eigenen Feld festzulegen.

Großmaul
quelle
0

Ich habe dieses Problem zu. Eine schnelle und freundliche Lösung für die Antwort von @Ken Steele. Ich erweitere die UITextView und füge eine berechnete Eigenschaft hinzu.

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

ich hoffe es hilft.

LastMove
quelle
0

Es ist 3 Jahre her und der Fehler existiert immer noch in der neuesten stabilen Version von Xcode (7.3). Es ist klar, dass Apple das Problem in naher Zukunft nicht beheben wird, sodass Entwickler zwei Optionen haben: Auswählbar aktivieren und UserInteractionEnabled auf false setzen oder Method swizzling.

Wenn Sie eine Schaltfläche in Ihrer Textansicht haben, reicht die erstere nicht aus.

Schnelle Lösung ohne Codeänderung:

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

Ziel 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
Mark Bourke
quelle
0

Unter Verwendung der in dieser Ausgabe beschriebenen Problemumgehung bietet diese Erweiterung von UITextView eine setTextInCurrentStyle()Funktion. Basierend auf der Lösung von Alessandro Ranaldi, erfordert jedoch nicht, dass der aktuelle isSelectable-Wert an die Funktion übergeben wird.

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