UITextView *_masterText
があり、メソッドsetText
を呼び出した後、プロパティフォントがリセットされています。 SDK 7を変更した後に発生します。_masterTextはIBOutlet
で、グローバルとプロパティはストーリーボードで設定されます。それは私だけですか、これは一般的なSDKのバグですか?
@interface myViewController : UIViewController
{
IBOutlet UITextView *_masterText;
}
@implementation myViewController
-(void)viewWillAppear:(BOOL)animated
{
[_masterText setText:@"New text"];
}
これを何時間も座って、バグを見つけました。プロパティ "Selectable" = NOの場合、setTextが使用されるときにフォントとフォントカラーがリセットされます。
そのため、Selectableをオンにすると、バグはなくなります。
(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
この問題を自分で解決し、上記の回答が役立ったが、次のように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];
}
}
この問題はXcode 8で再浮上しました。これは私が修正した方法です。
拡張機能を次のように変更しました:
extension UITextView{
func setTextAvoidXcodeIssue(newText : String, selectable: Bool){
isSelectable = true
text = newText
isSelectable = selectable
}
}
interface BuilderでSelectableオプションをチェックしました。
その「選択可能な」パラメータを持つことはあまりエレガントではありませんが、それは可能です。
編集:
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にテキストを追加して、フォントまたは色を変更すると機能します。
この問題に私がよく使用する簡単なサブクラスソリューションを次に示します。
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
}
}
}
IOS 8.3では、setTextの前に "selectable"をYESに設定し、その後にNOを設定する回避策は、それを修正しませんでした。
これが機能する前に、ストーリーボードでも「選択可能」を「はい」に設定する必要があることがわかりました。
これは私のために働いた:
let font = textView.font
textView.attributedText = attributedString
textView.font = font
属性付きテキストの場合、独自のフィールドに設定するのではなく、属性ディクショナリにフォントを設定するだけで済みました。
私はこの問題を抱えています。 @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;
}
}
}
それが役に立てば幸い。
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
この問題で説明した回避策を使用して、UITextViewのこの拡張機能はsetTextInCurrentStyle()
関数を提供します。 Alessandro Ranaldiによるソリューションに基づいていますが、現在のisSelectable値を関数に渡す必要はありません。
extension UITextView{
func setTextInCurrentStyle(_ newText: String) {
let selectablePreviously = self.isSelectable
isSelectable = true
text = newText
isSelectable = selectablePreviously
}
}