web-dev-qa-db-ja.com

UITextViewスタイルは、テキストプロパティの設定後にリセットされます

UITextView *_masterTextがあり、メソッドsetTextを呼び出した後、プロパティフォントがリセットされています。 SDK 7を変更した後に発生します。_masterTextはIBOutletで、グローバルとプロパティはストーリーボードで設定されます。それは私だけですか、これは一般的なSDKのバグですか?

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

@implementation myViewController

-(void)viewWillAppear:(BOOL)animated
{
    [_masterText setText:@"New text"];
}
145
Błażej

これを何時間も座って、バグを見つけました。プロパティ "Selectable" = NOの場合、setTextが使用されるときにフォントとフォントカラーがリセットされます。

そのため、Selectableをオンにすると、バグはなくなります。

450
Bosse Nilsson

(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
11
Ken Steele

テキストビューを「読み取り専用」にしたい場合は、[編集可能]および[選択可能]をオンにし、[ユーザーインタラクションを有効]をオフにします。これにより、UITextViewは期待どおりに動作しました

enter image description here

enter image description here

8
Chuy47

この問題を自分で解決し、上記の回答が役立ったが、次のように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];
    }
}
6
John Cogan

この問題はXcode 8で再浮上しました。これは私が修正した方法です。

拡張機能を次のように変更しました:

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

interface BuilderでSelectableオプションをチェックしました。

その「選択可能な」パラメータを持つことはあまりエレガントではありませんが、それは可能です。

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にテキストを追加して、フォントまたは色を変更すると機能します。

2
Jordan Montel

この問題に私がよく使用する簡単なサブクラスソリューションを次に示します。

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
WaltersGE1

IOS 8.3では、setTextの前に "selectable"をYESに設定し、その後にNOを設定する回避策は、それを修正しませんでした。

これが機能する前に、ストーリーボードでも「選択可能」を「はい」に設定する必要があることがわかりました。

1
Peter Johnson

これは私のために働いた:

let font = textView.font
textView.attributedText = attributedString
textView.font  = font
1
David Green

属性付きテキストの場合、独自のフィールドに設定するのではなく、属性ディクショナリにフォントを設定するだけで済みました。

0
loudmouth

私はこの問題を抱えています。 @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
LastMove

3年経ちましたが、バグはXcodeの最新の安定バージョン(7.3)にまだ存在しています。明らかにAppleはすぐに修正されることはなく、開発者に2つのオプションを選択できるようになります。

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
Mark Bourke

この問題で説明した回避策を使用して、UITextViewのこの拡張機能はsetTextInCurrentStyle()関数を提供します。 Alessandro Ranaldiによるソリューションに基づいていますが、現在のisSelectable値を関数に渡す必要はありません。

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