Стиль UITextView сбрасывается после установки свойства текста

145

У меня UITextView *_masterTextи после вызова метода setTextсвойство шрифта сбрасывается. Это происходит после того, как я меняю sdk 7. _masterText - это IBOutletглобальный и свойства устанавливаются в раскадровке. Это только у меня или это вообще баг SDK?

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

@implementation myViewController

-(void)viewWillAppear:(BOOL)animated
{
    [_masterText setText:@"New text"];
}
Błażej
источник

Ответы:

450

Сидя с этим часами, я нашел ошибку. Если свойство «Выбираемый» = НЕТ, оно сбросит шрифт и цвет шрифта при использовании setText.

Так что включите Selectable ON и ошибка исчезнет.

Боссе Нильссон
источник
15
Это происходит со мной также в Xcode 5. Мой обходной путь - временно установить selectable = YES перед вызовом setText:
Rollin_s
8
Вау, что за смешная ошибка. Спасибо за понимание!
Михей
3
Большое большое спасибо !
Магурицио
6
У 6.4 все еще есть эта проблема
RndmTsk
4
Похоже, это исправлено в iOS 10, если вы все еще ориентируетесь на iOS 9 или ниже, вам нужно будет обойти это.
user1184205
11

Я столкнулся с той же проблемой (на Xcode 6.1), и хотя ответ Джона Когана работал для меня, я обнаружил, что расширение класса UITextView категорией было лучшим решением для моего конкретного проекта.

интерфейс

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

реализация

@implementation UITextView (XcodeSetTextFormattingBugWorkaround)
- (void)setSafeText:(NSString *)textValue
{
    BOOL selectable = [self isSelectable];
    [self setSelectable:YES];
    [self setText:textValue];
    [self setSelectable:selectable];
}
@end
Кен Стил
источник
1
И по-быстрому:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }
маленькое
8

Если вы хотите, чтобы ваше текстовое представление было «только для чтения», вы можете выбрать «Редактируемый» и «Выбираемый» и снять флажок «Взаимодействие с пользователем включено», при этом UITextView ведет себя так, как я хотел

введите описание изображения здесь

введите описание изображения здесь

Chuy47
источник
3
На первый взгляд это кажется жизнеспособным решением, но в конечном итоге не является хорошим вариантом для UITextView. Обычно вы выбираете UITextView, потому что вам нужна прокручиваемая текстовая область. отключение взаимодействия с пользователем также отключает представление прокрутки. Для меня выбор использования UITextView был из-за того, что у меня была область, в которой нужно было разместить больше текста, чем уместилось бы в этой области, и иметь возможность прокручиваться.
Джелзер
6

Помогла ли мне эта проблема, и приведенный выше ответ помог, но я добавил обертку к своему коду ViewController следующим образом и просто передаю экземпляр и текст uiview для изменения, а функция обертки включает значение Selectable, изменяет текст, а затем снова выключает его. Полезно, когда вам необходимо отключить uitextview по умолчанию.

/*
    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
Может быть, лучше создать подкласс UITextView, переопределить setText и использовать свой подкласс в приложении
powerj1984,
2

РЕДАКТИРОВАТЬ :

Настройка шрифта для UITextView в iOS 7 работает для меня, если сначала вы установите текст, а затем установите шрифт:

@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

}

В XIB-файле, если вы добавите некоторый текст в UITextView и измените шрифт или цвет, он будет работать.

Джордан Монтел
источник
хм .. Я использую собственность, но без изменений.
Błażej
забыл [супер просмотрWillAppear: анимированный];
Джордан Монтел
Я забыл об этом, но это не повлияло :(
Błażej
очистите и перезапустите ваш XCode, потому что он прекрасно работает без строки "_myTextView.font ...", даже если я изменю шрифт из файла XIB
Jordan Montel
Очистить, перезагрузить и без эффекта. Проект> iOS Deployment Target 7.0, Base SDK 7.0 в целевых настройках.
Błażej
2

Вот быстрое решение подкласса, которое я часто использую для этой проблемы.

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
источник
2

Эта проблема вновь появилась в Xcode 8. Вот как я это исправил:

Изменено расширение на:

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

и проверил опцию Выбираемый в Интерфейсном Разработчике.

Не очень элегантно иметь этот «выбираемый» параметр, но он подойдет.

Алессандро Ранальди
источник
1

В iOS 8.3 обходной путь установки «выбираемого» в YES до setText и NO после этого не исправил это для меня.

Я обнаружил, что мне нужно было также установить «selectable» на YES в раскадровке, прежде чем это сработает.

Питер Джонсон
источник
Вы спасли мой день, я считаю, что это еще одна нелепая ошибка в CocoaTouch
Крис
1

Это сработало для меня:

let font = textView.font
textView.attributedText = attributedString
textView.font  = font
Дэвид Грин
источник
0

Для меня с атрибутивным текстом мне просто нужно было установить шрифт в словаре атрибутов, а не устанавливать его в своем собственном поле.

крикун
источник
0

У меня возникла эта проблема. Удобное решение ответа на вопрос @Ken Steele. Я расширяю UITextView и добавляю вычисляемое свойство.

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

Надеюсь, поможет.

LastMove
источник
0

Прошло 3 года, и ошибка все еще существует в последней стабильной версии Xcode (7.3). Очевидно, что Apple не будет исправлять это в ближайшее время, предоставляя разработчикам две опции: оставляя selectable on и устанавливая UserInteractionEnabled в false или Method swizzling.

Если у вас есть кнопка в вашем textView, первого будет недостаточно.

Решение, не требующее изменения кода в 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
        }
    }
}

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

Используя обходной путь, обсуждаемый в этом выпуске, это расширение UITextView предоставляет setTextInCurrentStyle()функцию. Основано на решении Алессандро Ранальди, но не требует, чтобы текущее значение isSelectable передавалось функции.

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
Дункан Бэббидж
источник