Swift 中带有 UITextView 属性 的自定义 UIView 加载时间缓慢

Slow load time for custom UIView with UITextView property in Swift

我最初问的是this question. I had assumed that the reason for the slow load time of my custom view was because of layering multiple views on top of each other or perhaps because of some recursion problem。然而,在删除越来越多的代码以查看有什么不同之后,归结为我是否有 UITextView 礼物。因为我的问题的明显根源与我在第一个问题中所期望的完全不同,所以我决定开始一个新问题而不是对旧问题添加冗长的更新。

我用两个视图控制器设置了我的测试项目。第一个视图控制器上的按钮调用第二个视图控制器的 show segue。第二个视图控制器上有我的自定义视图。 (使用第二个视图控制器让我了解加载自定义视图需要多长时间。)

自定义视图代码:

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 中的分配工具我得到以下结果(计数为 997):

但是,如果我注释掉该行

    //var textView = UITextView()

然后我的自定义视图加载速度非常快,并且只有 7 个计数。

这是怎么回事?是否可以在自定义视图中使用 UITextView 属性 并避免这种缓慢的加载时间?

从 github 下载了您的代码,为什么不直接编写 UITextView 的子类而不是 UIView?

//
//  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
    }
}

瓶颈是您的 UITextView 的 selectable 属性。在将 selectable 设置为其默认值 true 的 UITextView 创建时存在莫名其妙的性能问题。

解决该问题的最简单方法是使用故事板添加文本视图,确保取消勾选 selectable 属性。似乎没有记录在代码中创建不可选择的文本视图的方法(因为在创建后将 selectable 设置为 false 并不能避免创建期间的性能问题)。如果需要可选择的文本视图,首先创建一个不可选择的文本视图,然后在viewDidAppear.

中将selectable设置为true

如果你不能使用故事板,你可能要考虑使用第三方 class 例如 TTTAttributedLabel.

看起来 Apple 使用私有 API 来避免这个问题。其他有进取心的开发人员 discovered 在 ChatKit 中,文本视图似乎是使用名为 initReadonlyAndUnselectableWithFrame:textContainer:.

的私有方法创建的

尝试了类似的方法,将标签和文本字段作为子视图添加到 uiview 子类中。我的做法如下:

@interface CustomTextField : UIView

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

@end

所以,我们有一个 xib 文件,我们在上面实际添加了标签和文本字段。 在 xib 文件上,文件所有者是 "CustomTextField" 并且 outlets 与那里的头文件链接。

构造方法如下所示:

- (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;
}

适合我。

我遇到了与 UITextView 非常相似的性能问题,但我认为根本原因和解决方案对我来说是不同的。

我在故事板上有一个带有静态文本的 UITextView。它不可编辑或可选择。在较慢的 iPod Touch 上,ViewController 需要 5 秒才能加载。

原来我在静态文本中有一个表情符号。当我删除表情符号时,问题就消失了!我使用仪器来深入了解正在发生的事情,并且在它进入一堆......字体......方法的跟踪中大约有 25 个级别。我使用的是没有属性的系统字体,所以第一个想到的是我文本中的表情符号字符。