设置文本属性后将重置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"];
}

Answers:


450

坐了几个小时,我发现了这个错误。如果属性“ Selectable” = NO,则在使用setText时将重置字体和字体颜色。

因此,将Selectable设为ON,该错误将消失。


15
这也发生在Xcode 5中。我的解决方法是在调用setText之前临时设置selectable = YES:
Rollin_s 2013年

8
哇,真是可笑的错误。感谢您的见解!
米卡2013年

3
非常非常感谢你 !
Magurizio

6
6.4仍然存在此问题
RndmTsk

4
这似乎已在iOS 10中修复,如果您仍以iOS 9或更低版本为目标,则需要采取解决方法。
user1184205 '16

11

我遇到了相同的问题(在Xcode 6.1上),尽管John Cogan的答案对我有用,但我发现用类别扩展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
而在SWIFT:extension UITextView { func setSafeText(text: String){ let originalSelectable = selectable selectable = true self.text = text selectable = originalSelectable } }

8

如果您希望文本视图为“只读”,则可以选中“可编辑”和“可选”,然后取消选中“启用用户交互”,以此,UITextView的运行方式如我所愿

在此处输入图片说明

在此处输入图片说明


3
从表面上看,这似乎是一个可行的解决方案,但是对于UITextView而言,最终并不是一个好的选择。通常,您选择UITextView是因为您需要可滚动的文本区域。禁用用户交互也会禁用滚动视图。对我来说,使用UITextView的选择是因为我有一个区域需要容纳的文本超出该区域的容纳范围,并且需要滚动。
jhelzer

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
最好
继承

2

编辑:

如果先设置文本,然后再设置字体,那么在iOS 7中为UITextView设置字体对我有用。

@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

忘记了[super viewWillAppear:animated];
Jordan Montel 2013年

我忘了,但是这并没有影响:(
Błażej

清理并重新启动您的XCode,因为即使我从XIB文件中更改了字体,
乔丹·蒙特尔

清洁,重新启动,没有效果。项目> iOS部署目标7.0,目标中的基本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
        }
    }
}

2

这个问题在Xcode 8中浮出水面。这是我解决的方法:

将扩展名更改为:

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

并在“界面生成器”中选中了“可选”选项。

拥有“ selectable”参数不是很好,但是可以做到。


1

在iOS 8.3中,将setText之前的“ selectable”设置为YES,之后将NO设置为NO的变通办法并没有为我解决。

我发现我也需要在情节提要中将“可选”设置为“是”,然后才能起作用。


您保存了我的一天,我相信这只是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;
        }
    }
}

希望能帮助到你。


0

已经3年了,该错误仍然存​​在于最新的Xcode稳定版本(7.3)中。显然,Apple不会很快修复它,而给开发人员留下了两个选择:将select保持打开状态并将UserInteractionEnabled设置为false或Method swizzling。

如果您的textView上有一个按钮,则前者不足。

快速无需代码更改的解决方案:

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

目标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()功能。基于Alessandro Ranaldi的解决方案,但不需要将当前isSelectable值传递给该函数。

extension UITextView{
    func setTextInCurrentStyle(_ newText: String) {
        let selectablePreviously = self.isSelectable
        isSelectable = true
        text = newText
        isSelectable = selectablePreviously
    }
}
By using our site, you acknowledge that you have read and understand our Cookie Policy and Privacy Policy.
Licensed under cc by-sa 3.0 with attribution required.