Styl UITextView jest resetowany po ustawieniu właściwości text


145

Mam UITextView *_masterTexti po wywołaniu metody setTextjest resetowana czcionka właściwości. Dzieje się to po zmianie sdk 7. _masterText jest IBOutletglobalne, a właściwości są ustawione w scenorysie. To tylko ja czy to ogólny błąd SDK?

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

@implementation myViewController

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

Odpowiedzi:


450

Siedząc z tym godzinami, znalazłem błąd. Jeśli właściwość „Selectable” = NO, zresetuje czcionkę i kolor czcionki, gdy zostanie użyta funkcja setText.

Więc włącz opcję Selectable, a błąd zniknie.


15
Dzieje się tak również w Xcode 5. Moje obejście polega na tymczasowym ustawieniu
selectable

8
Wow, co za śmieszny błąd. Dzięki za wgląd!
Micah

3
Dziękuje bardzo !
Magurizio,

6
6.4 nadal ma ten problem
RndmTsk

4
Wydaje się, że problem został rozwiązany w systemie iOS 10, jeśli nadal kierujesz reklamy na system iOS 9 lub starszy, musisz obejść ten problem.
user1184205

11

Natknąłem się na ten sam problem (na Xcode 6.1) i podczas odpowiedzi Johna Cogana zadziałała dla mnie, stwierdziłem, że rozszerzenie klasy UITextView o kategorię było lepszym rozwiązaniem dla mojego konkretnego projektu.

berło

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

realizacja

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

1
I szybko:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }
mały

8

Jeśli chcesz, aby Twój widok tekstu był „tylko do odczytu”, możesz zaznaczyć Edytowalne i Wybieralne oraz odznaczyć opcję Interakcja z użytkownikiem Włączona, z tym UITextView zachowywał się tak, jak chciałem

wprowadź opis obrazu tutaj

wprowadź opis obrazu tutaj


3
Wydaje się, że jest to realne rozwiązanie, ale ostatecznie nie jest dobrą opcją dla UITextView. Zwykle wybierasz UITextView, ponieważ potrzebujesz przewijalnego obszaru tekstowego. wyłączenie interakcji użytkownika wyłącza również widok przewijania. Dla mnie wybór użycia UITextView był spowodowany tym, że miałem obszar, który musiał pomieścić więcej tekstu, niż mogłoby się zmieścić w tym obszarze i móc przewijać.
jhelzer

6

Gdyby ten problem i powyższa odpowiedź pomogły, ale dodałem otokę do mojego kodu ViewController w następujący sposób i po prostu przekazałem wystąpienie uiview i tekst do zmiany, a funkcja opakowania włącza wartość Selectable, zmienia tekst, a następnie wyłącza ją ponownie. Przydatne, gdy chcesz, aby uitextview był domyślnie wyłączony przez cały czas.

/*
    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
Może lepiej będzie podklasować UITextView i przesłonić setText i użyć swojej podklasy w aplikacji
powerj1984

2

EDYTOWAĆ :

Ustawienie czcionki dla UITextView w iOS 7 działa dla mnie, jeśli najpierw ustawisz tekst, a następnie ustawisz czcionkę:

@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

}

W pliku XIB, jeśli dodasz tekst w swoim UITextView i zmienisz czcionkę lub kolor, to zadziała.


hmm .. Używam nieruchomości, ale bez zmian.
Błażej

zapomniałem [super viewWillAppear: animated];
Jordan Montel,

Zapomniałem o tym, ale to nie miało wpływu :(
Błażej

wyczyść i zrestartuj XCode, ponieważ dla mnie działa dobrze bez wiersza "_myTextView.font ...", nawet jeśli zmienię czcionkę z pliku XIB
Jordan Montel

Czyste, uruchom ponownie i bez efektu. Projekt> cel wdrożenia systemu iOS 7.0, podstawowy zestaw SDK 7.0 w miejscu docelowym z tymi samymi ustawieniami.
Błażej

2

Oto szybkie rozwiązanie podklasy, którego często używam w przypadku tego problemu.

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

Ten problem powrócił w Xcode 8. Oto jak go naprawiłem:

Zmieniono rozszerzenie na:

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

i zaznaczono opcję Wybieralne w programie Interface Builder.

Posiadanie tego „wybieralnego” parametru nie jest zbyt eleganckie, ale wystarczy.


1

W iOS 8.3 obejście ustawienia „selectable” na YES przed setText i NO po, nie rozwiązało tego problemu.

Zauważyłem, że muszę ustawić opcję „do wyboru” na TAK w scenorysie, zanim to zadziała.


Uratowałeś mi dzień, myślę, że to tylko kolejny śmieszny błąd w CocoaTouch
Chris

1

To zadziałało dla mnie:

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

0

Dla mnie z przypisanym tekstem wystarczyło ustawić czcionkę w słowniku atrybutów, zamiast ustawiać ją we własnym polu.


0

Mam ten problem. Szybkie i przyjazne rozwiązanie odpowiedzi @Ken Steele. Rozszerzam UITextView i dodaję właściwość obliczoną.

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

mam nadzieję, że to pomoże.


0

Minęły już 3 lata, a błąd nadal istnieje w najnowszej stabilnej wersji Xcode (7.3). Najwyraźniej Apple nie naprawi tego w najbliższym czasie, pozostawiając programistom dwie opcje: pozostawienie wyboru włączonego i ustawienie UserInteractionEnabled na false lub swizzling Method.

Jeśli masz przycisk na swoim textView, pierwszy nie wystarczy.

Szybkie rozwiązanie wymagające zmiany kodu:

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

Cel 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

Korzystając z obejścia omówionego w tym problemie, to rozszerzenie UITextView udostępnia setTextInCurrentStyle()funkcję. Oparty na rozwiązaniu Alessandro Ranaldiego, ale nie wymaga przekazywania bieżącej wartości isSelectable do funkcji.

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
Korzystając z naszej strony potwierdzasz, że przeczytałeś(-aś) i rozumiesz nasze zasady używania plików cookie i zasady ochrony prywatności.
Licensed under cc by-sa 3.0 with attribution required.