web-dev-qa-db-ja.com

Swift)のUITextViewプロパティを使用したカスタムUIViewの読み込み時間が遅い

私は最初に尋ねました この質問 。カスタムビューの読み込み時間が遅い理由は、複数のビューを重ねて表示するためか、 再帰の問題 が原因であると考えていました。しかし、何が違いを生むかを確認するためにコードをどんどん切り取った後、UITextViewが存在するかどうかにかかった。私の問題の明らかな原因は最初の質問で予想していたものとは非常に異なるため、古い質問に長い更新を追加するのではなく、新しい質問を開始することにしました。

2つのViewControllerを使用してテストプロジェクトを設定しました。最初のビューコントローラのボタンは、2番目のビューコントローラにショーセグエを呼び出します。 2番目のViewControllerには、カスタムビューがあります。 (2番目のView Controllerを使用すると、カスタムビューのロードにかかった時間を知ることができます。)

カスタムビューコード:

import UIKit

@IBDesignable class UIMongolTextView: UIView {

    var textView = UITextView() // key line

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
    }

    override init(frame: CGRect){
        super.init(frame: frame)
    }
}

ご覧のとおり、UIViewとの唯一の違いは、UITextViewプロパティを追加したことです。そして、ロードが非常に遅いのはこのカスタムビューです。 InstrumentsでAllocationsツールを実行すると、次の結果が得られます(997のカウント)。

enter image description here

ただし、コメントアウトすると

    //var textView = UITextView()

次に、カスタムビューは非常にすばやく読み込まれ、カウントは7しかありません。

enter image description here

ここで何が起こっているのですか?カスタムビューでUITextViewプロパティを使用して、この遅い読み込み時間を回避することは可能ですか?

27
Suragch

ラベルとテキストフィールドがサブビューとしてuiviewサブクラスに追加された同様のことを試みました。私がした方法は次のとおりでした:

@interface CustomTextField : UIView

@property (weak, nonatomic) IBOutlet UITextField *valueField;

@end

そのため、実際にラベルとテキストフィールドを追加するxibファイルがありました。 xibファイルでは、ファイルの所有者は「CustomTextField」であり、アウトレットはそこからヘッダーファイルにリンクされています。

コンストラクターメソッドは次のようになります。

- (id)initWithValue:(NSString *)value
{
    self = [super initWithFrame:CGRectZero];
    if (self) {
        NSArray *nibs = [[NSBundle mainBundle] loadNibNamed:NSStringFromClass([self class]) owner:self options:nil];
        UIView *view = nibs[0];
        self.valueField.frame = view.bounds;
        [self setFrame:view.bounds];
        [self addSubview:view];
        [self.valueField setText:value];
    }

    return self;
}

私にとってはうまくいきます。

3
Anand

ボトルネックは、UITextViewのselectableプロパティです。 selectableをデフォルト値のtrueに設定したUITextViewの作成には、説明できないパフォーマンスの問題があります。

この問題を回避する最も簡単な方法は、ストーリーボードを使用してテキストビューを追加し、selectableプロパティのチェックを外すことです。コードで選択できないテキストビューを作成する文書化された方法はないようです(作成後にselectableをfalseに設定しても、作成中のパフォーマンスの問題を回避できないため)。選択可能なテキストビューが必要な場合は、最初に選択不可能なテキストビューを作成してから、viewDidAppearでselectableをtrueに設定します。

ストーリーボードを使用できない場合は、 TTTAttributedLabel などのサードパーティクラスの使用を検討することをお勧めします。

Appleはこの問題を回避するためにプライベートAPIを使用しているようです。他の進取的な開発者は 発見 、ChatKitではテキストビューはと呼ばれるプライベートメソッドを使用して作成されているように見えますinitReadonlyAndUnselectableWithFrame:textContainer:

27
jamesk

githubからコードをダウンロードしました。UIViewの代わりにUITextViewのサブクラスを書いてみませんか?

//
//  UIMongolTextView-A.Swift
//  Mongol App Componants
//
//  Created by Allen Zhang on 12/13/15.
//  Copyright © 2015 MongolSuragch. All rights reserved.
//

import UIKit

class UIMongolTextView_A: UITextView {

    override func awakeFromNib() {
        super.awakeFromNib()
        self.setup()
    }

    func setup() {
        // 1-10: ᠨᠢᠭᠡ ᠬᠤᠶᠠᠷ ᠭᠤᠷᠪᠠ ᠳᠦᠷᠪᠡ ᠲᠠᠪᠤ ᠵᠢᠷᠭᠤᠭ᠎ᠠ ᠳᠤᠯᠤᠭ᠎ᠠ ᠨᠠᠢ᠌ᠮᠠ ᠶᠢᠰᠦ ᠠᠷᠪᠠ

        self.transform = translateRotateFlip()


    }

    /*
    // Only override drawRect: if you perform custom drawing.
    // An empty implementation adversely affects performance during animation.
    override func drawRect(rect: CGRect) {
        // Drawing code
    }
    */
    func translateRotateFlip() -> CGAffineTransform {

        var transform = CGAffineTransformIdentity

        // translate to new center
        transform = CGAffineTransformTranslate(transform, (self.bounds.width / 2)-(self.bounds.height / 2), (self.bounds.height / 2)-(self.bounds.width / 2))
        // rotate counterclockwise around center
        transform = CGAffineTransformRotate(transform, CGFloat(-M_PI_2))
        // flip vertically
        transform = CGAffineTransformScale(transform, -1, 1)

        return transform
    }
}
1
Allen

UITextViewで非常によく似たパフォーマンスの問題が発生しましたが、根本的な原因と解決策が異なっていたと思います。

ストーリーボードに静的テキストを含むUITextViewがありました。編集も選択もできませんでした。遅いiPodTouchでは、ViewControllerのロードに5秒かかります。

静的テキストに絵文字が含まれていることがわかりました。絵文字を削除すると、問題は解決しました。私は楽器を使って何が起こっているのかを掘り下げ、トレースの約25レベルの深さで... font ...メソッドの束に入りました。属性のないシステムフォントを使用していたので、最初に頭に浮かんだのはテキストの絵文字です。

1
Chad Pavliska