UITextView设置文本属性后,样式被重置

146

我有一个UITextView *_masterText,在调用方法setText后,字体属性会被重置。这是发生在我更新SDK 7之后的情况。_masterText是一个IBOutlet,是全局的,在storyboard中设置了属性。这是只有我遇到的问题还是普遍存在的SDK bug?

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

@implementation myViewController

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

451

我花数小时的时间发现了这个bug。如果属性"Selectable" = NO,则在使用setText时将重置字体和字体颜色。

因此,开启Selectable功能,该bug即可消失。


15
在Xcode 5中,我也遇到过这个问题。我的解决方法是在调用setText之前暂时将selectable设置为YES。 - Rollin_s
2
@John 是的,你只需要将 selectable 设置为 TRUE,设置文本,然后再将 selectable 设置为 FALSE。这在 6.3.1 中仍然是一个 bug。 - ChrisH
在iOS 8.3中,仅在setText之前将"selectable"设置为YES,之后再设置为NO并不能解决我的问题。我发现在Storyboard中也需要将"selectable"设置为YES。 - Peter Johnson
我认为这个错误与iOS版本有关,而不是Xcode版本。并且似乎在我到目前为止测试的所有8.x版本中都存在。 - Christophe Fondacci
4
如果你仍然要面向 iOS 9 或更低版本,那么你需要采取变通方法。但这个问题似乎已经在 iOS 10 中得到修复了。 - user1184205
显示剩余3条评论

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

8

如果您希望文本视图为“只读”,则可以勾选可编辑和可选择,并取消用户交互启用,这样UITextView将按照我的要求进行操作

enter image description here

enter image description here


3
这个看起来表面上是可行的解决方案,但对于UITextView来说最终并不是一个好选择。通常你会选择UITextView因为你需要一个可滚动的文本区域。禁用用户交互也会禁用滚动视图。我选择使用UITextView是因为我有一个需要容纳更多文字而无法全部显示的区域,并且需要能够滚动。 - jhelzer

6

我自己也遇到了这个问题,上面的答案有所帮助,但是我在我的ViewController代码中添加了一个包装器(wrapper)函数,只需要传递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

编辑:

如果你先设置文本,然后再设置字体,那么在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
清理并重新启动您的XCode,因为即使我从XIB文件更改字体,它对我来说也可以正常工作,而无需使用“_myTextView.font…”这行代码。 - Jordan Montel
清理、重新启动,但没有效果。在项目中> iOS部署目标7.0,基本SDK 7.0与目标相同的设置。 - Błażej
我有完全相同的配置,只是我的代码在viewDidLoad中。 - Jordan Montel
显示剩余6条评论

2

这个问题在Xcode 8中再次出现了。以下是我解决它的方法:

将文件扩展名更改为:

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

并在Interface Builder中勾选了“可选择”选项。

这个“可选择”参数并不是很优雅,但是它可以做到任务。


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

1
这对我有效:

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

1
在iOS 8.3中,在setText之前将"selectable"设置为YES,之后再将其设置为NO的方法对我没有起作用。我发现我需要在storyboard中也将"selectable"设置为YES,才能使其正常工作。

你救了我一天的工作,我相信这只是CocoaTouch中又一个荒谬的bug。 - Eddie Deng

0

我也遇到了这个问题。 @Ken Steele 的答案的一个适用于 Swift 的解决方案。 我扩展了 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;
        }
    }
}

希望它有所帮助。

网页内容由stack overflow 提供, 点击上面的
可以查看英文原文,
原文链接