텍스트 속성을 설정 한 후 UITextView 스타일이 재설정됩니다


145

내가 가진 UITextView *_masterText및 호출 방법 후 setText속성 글꼴되고 재설정됩니다. SDK 7을 변경하면 발생합니다. _masterText is IBOutlet, global 및 속성이 스토리 보드에 설정되어 있습니다. 나만 아니면 일반 SDK 버그입니까?

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

@implementation myViewController

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

답변:


450

몇 시간 동안 이것과 함께 앉아 버그를 발견했습니다. "Selectable"= NO 속성 인 경우 setText를 사용할 때 글꼴 및 글꼴 색상이 재설정됩니다.

선택 가능을 켜면 버그가 사라집니다.


15
이 문제는 Xcode 5에서도 발생합니다. 해결 방법은 setText를 호출하기 전에 selectable = YES를 임시로 설정하는 것입니다.
Rollin_s

8
와우, 우스운 버그. 통찰력에 감사드립니다!
Micah

3
대단히 감사합니다!
Magurizio

6
6.4 여전히이 문제가 있습니다
RndmTsk

4
여전히 iOS 9 이하를 대상으로하는 경우 해결 방법을 수행 해야하는 경우 iOS 10에서 수정 된 것으로 보입니다.
user1184205

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
그리고 신속하게 :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 인스턴스와 텍스트를 전달하여 변경하면 래퍼 함수가 선택 가능 값을 설정하고 텍스트를 변경 한 다음 다시 끕니다. 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

나는 그것을 잊어
버렸지 만

XIB 파일에서 글꼴을 변경 한 경우에도 "_myTextView.font ..."줄이 없어도 XCode를 정리하고 다시 시작할 수 있습니다.
Jordan Montel

깨끗하고 다시 시작하며 효과가 없습니다. Project> iOS Deployment Target 7.0, Base 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
    }
}

Interface Builder에서 Selectable 옵션을 확인했습니다.

그 '선택 가능'매개 변수를 갖는 것은 그리 우아하지 않지만 그렇게 할 것입니다.


1

iOS 8.3의 경우 setText 전에 "selectable"을 YES로 설정 한 후 NO로 설정하면 해결되지 않았습니다.

스토리 보드에서도 "selectable"을 YES로 설정해야한다는 것을 알았습니다.


당신은 내 하루를 저장, 나는 이것이 CocoaTouch의 또 다른 우스운 버그라고 생각합니다
Chris

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)에 존재합니다. 분명히 애플은 두 가지 옵션, 즉 선택 가능 상태를 유지하고 UserInteractionEnabled를 false 또는 메소드 스위 즐링으로 설정하는 두 가지 옵션으로 개발자를 떠날 때마다 곧 고치지 않을 것입니다.

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
    }
}
당사 사이트를 사용함과 동시에 당사의 쿠키 정책개인정보 보호정책을 읽고 이해하였음을 인정하는 것으로 간주합니다.
Licensed under cc by-sa 3.0 with attribution required.