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

时间:2013-09-27 11:43:49

标签: ios cocoa-touch fonts uitextview

我有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 个答案:

答案 0 :(得分:450)

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

因此,将Selectable设置为ON,错误就消失了。

答案 1 :(得分:11)

我遇到了同样的问题(在Xcode 6.1上),当John Cogan's answer为我工作时,我发现用类别扩展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

答案 2 :(得分:8)

如果您希望文本视图为“只读”,则可以选中“可编辑”和“可选择”并取消选中“启用用户交互”,此时UITextView的行为符合我的要求

enter image description here

enter image description here

答案 3 :(得分:6)

这个问题本身和上面的答案有所帮助,但我在我的ViewController代码中添加了一个包装器,如下所示,只需传递uiview实例和文本进行更改,包装函数切换可选值,更改文本然后将其关闭再次。如果您在默认情况下需要关闭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];
    }
}

答案 4 :(得分: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中添加一些文本并更改它将起作用的字体或颜色。

答案 5 :(得分: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
        }
    }
}

答案 6 :(得分:2)

这个问题在Xcode 8中重新出现。这就是我修复它的方法:

将扩展名更改为:

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

并选中Interface Builder中的Selectable选项。

拥有可选择的'并不是很优雅。参数,但它会做。

答案 7 :(得分:1)

在iOS 8.3中,在setText之前将“selectable”设置为YES以及之后没有设置的解决方法并没有为我修复它。

我发现我需要在故事板中将“可选”设置为YES,然后再进行操作。

答案 8 :(得分:1)

这对我有用:

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

答案 9 :(得分: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;
        }
    }
}
希望它有所帮助。

答案 10 :(得分:0)

对于带有属性文本的我,我只需要在属性字典中设置字体,而不是将其设置在自己的字段中。

答案 11 :(得分:0)

已经有3年了,这个bug仍然存在于Xcode(7.3)的最新稳定版本中。很明显苹果不会很快修复它,让开发人员有两个选择:保持selectable并将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
        }
    }
}

目标-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

答案 12 :(得分:0)

使用本期讨论的解决方法,UITextView的此扩展提供了setTextInCurrentStyle()功能。基于Alessandro Ranaldi的解决方案,但不要求将当前的isSelectable值传递给函数。

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