You need to enable JavaScript to run this app.
优惠活动
大模型
产品
解决方案
定价
更多

从Storyboard创建UITextView实例时,如何注册CustomLayoutManager

解决Storyboard初始化CustomTextView时注册CustomLayoutManager的问题

当你从Storyboard/XIB创建CustomTextView实例时,系统会调用init?(coder:)这个required初始化方法,而非你自定义的init(frame:textContainer:)。所以我们需要在这个方法里也完成CustomLayoutManager的配置,替换掉系统默认的布局管理器。

下面是完整的实现代码:

final class CustomTextView: UITextView {
    // 代码初始化时的逻辑保持不变
    override init(frame: CGRect, textContainer: NSTextContainer?) {
        let storage = NSTextStorage()
        let layout = CustomLayoutManager()
        storage.addLayoutManager(layout)
        let container = NSTextContainer()
        container.widthTracksTextView = true
        layout.addTextContainer(container)
        super.init(frame: frame, textContainer: container)
    }
    
    // Storyboard/XIB初始化时的核心逻辑
    required init?(coder: NSCoder) {
        super.init(coder: coder)
        
        // 确保能获取到当前textContainer,避免空值崩溃
        guard let textContainer = self.textContainer else { return }
        
        // 解除系统默认组件的关联,避免重复引用或布局冲突
        let defaultLayout = textContainer.layoutManager
        defaultLayout?.removeTextContainer(textContainer)
        defaultLayout?.textStorage?.removeLayoutManager(defaultLayout!)
        
        // 创建自定义的文本处理组件
        let customStorage = NSTextStorage()
        let customLayout = CustomLayoutManager()
        
        // 建立正确的关联链:textStorage → layoutManager → textContainer
        customStorage.addLayoutManager(customLayout)
        customLayout.addTextContainer(textContainer)
        
        // 同步Storyboard中设置的初始文本/属性文本
        if let attributedText = self.attributedText {
            customStorage.setAttributedString(attributedText)
        }
        
        // 替换textView的textStorage,让自定义布局生效
        self.textStorage = customStorage
    }
}

关键细节说明:

  • 调用super.init(coder:)后,textView已经自带了默认的textStorage、layoutManager和textContainer,必须先解除它们的关联,否则会出现重复布局或内存泄漏问题。
  • 同步原有文本内容很关键,不然你在Storyboard里设置的占位文本、初始文本会丢失。
  • 替换textStorage后,textView会自动使用我们的CustomLayoutManager处理文本布局。

这样不管是通过代码初始化,还是从Storyboard拖入创建CustomTextView,都能正确用上你的CustomLayoutManager啦!

内容的提问来源于stack exchange,提问作者toyu

相关产品推荐
方舟 Agent Plan

超全模态模型 × Harness 升级,最新支持 Deepseek-V4.1-Flash、GLM-5.3 系列、Doubao-Seedream-5.0-pro、Kimi-K3 (部分), 限时 9.9 元起

最近更新时间:2026.05.21 06:25:06