1

バックグラウンド

縦スクロールのモンゴル文字を横スクロールするテキストビューを作るために、カスタムUIViewサブクラスを作りました。このクラスは を取り、UITextViewそれを にUIView入れ、そのビューを回転および反転させてから、そのビューを 親 に入れUIViewます。

ここに画像の説明を入力

回転と反転の目的は、テキストが垂直になり、行の折り返しが正しく機能するようにすることです。すべてを親に貼り付ける目的はUIView、自動レイアウトがストーリーボードで機能するようにすることです。(詳細はこちらをご覧ください。)

コード

私は実用的な解決策を得ました。github の完全なコードはこちらにありますが、新しいプロジェクトを作成し、問題を切り分けるためにできる限り不要なコードをすべて取り除きました。次のコードは、上記の基本的な機能を引き続き実行しますが、以下に説明する読み込みが遅いという問題もあります。

import UIKit

@IBDesignable class UIMongolTextView: UIView {

    private var view = UITextView()
    private var oldWidth: CGFloat = 0
    private var oldHeight: CGFloat = 0

    @IBInspectable var text: String {
        get {
            return view.text
        }
        set {
            view.text = newValue
        }
    }

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

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

    override func sizeThatFits(size: CGSize) -> CGSize {
        // swap the length and width coming in and going out
        let fitSize = view.sizeThatFits(CGSize(width: size.height, height: size.width))
        return CGSize(width: fitSize.height, height: fitSize.width)
    }

    override func layoutSubviews() {
        super.layoutSubviews()

        // layoutSubviews gets called multiple times, only need it once
        if self.frame.height == oldHeight && self.frame.width == oldWidth {
            return
        } else {
            oldWidth = self.frame.width
            oldHeight = self.frame.height
        }

        // Remove the old rotation view
        if self.subviews.count > 0 {
            self.subviews[0].removeFromSuperview()
        }

        // setup rotationView container
        let rotationView = UIView()
        rotationView.frame = CGRect(origin: CGPointZero, size: CGSize(width: self.bounds.height, height: self.bounds.width))
        rotationView.userInteractionEnabled = true
        self.addSubview(rotationView)

        // transform rotationView (so that it covers the same frame as self)
        rotationView.transform = translateRotateFlip()

        // add view
        view.frame = rotationView.bounds
        rotationView.addSubview(view)

    }

    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
    }

}

問題

カスタム ビューの読み込みが非常に遅いことに気付きました。私は Xcode Instruments を初めて使用するので、役に立つビデオDebugging Memory Issues with Xcode and ProfilerおよびTime Profilerを見ました。

その後、自分のプロジェクトで問題を見つけようとしました。Time Profiler、Leaks、Allocations ツールのいずれを使用しても、クラスinitメソッドの処理が多すぎることがわかります。(しかし、以前の読み込み時間が遅いことから、それはすでに知っていました。)これは、割り当てツールのスクリーンショットです。

ここに画像の説明を入力

収まらないため、呼び出しツリーのすべてを展開しませんでした。なぜこれほど多くのオブジェクトが作成されるのでしょうか? 3 層のカスタム ビューを作成したとき、それが理想的ではないことはわかっていましたが、コール ツリーから発生しているように見える層の数はばかげています。私は何を間違っていますか?

4

1 に答える 1

2

内のサブビューを追加または削除しないでください。layoutSubviewsこれを行うと、再度呼び出しがトリガーさlayoutSubviewsれます。

ビューを作成するときにサブビューを作成し、layoutSubviews削除して再度追加するのではなく、その位置を調整するだけです。

于 2015-12-07T14:03:26.383 に答える