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

使用UIViewControllerRepresentable(无storyboard)时子视图尺寸布局异常

问题根因

你遇到的UITextView内容超出屏幕无法换行的问题,核心有两个错误点:

  1. CustomUIViewController 中的UITextView没有设置初始frame,仅设置autoresizingMask不会自动匹配父视图尺寸
  2. viewWillLayoutSubviews 中的尺寸计算逻辑错误,sizeToFit() 会优先按照文本内容的最大宽度计算尺寸,不会限制在父视图的宽度范围内,导致textView横向超出屏幕

修复方案

步骤1:修改CustomUIViewController实现

替换原有CustomUIViewController的代码如下,核心修改点:

  • 给textView设置初始frame匹配父视图
  • 修正布局回调中的尺寸逻辑
class CustomUIViewController: UIViewController {
    var textView: UITextView = UITextView()
    var tapGesture: UITapGestureRecognizer!
    
    override func viewDidLoad() {
        super.viewDidLoad()
        // 初始frame匹配父视图
        textView.frame = view.bounds
        tapGesture = UITapGestureRecognizer(target: self, action: #selector(handleTap(recognizer:)))
        self.textView.addGestureRecognizer(tapGesture)
        self.textView.isEditable = false
        self.textView.isSelectable = false
        self.textView.clipsToBounds = true
        
        self.textView.text = """
            This is some text that will need to be displayed on multiple lines as it's longer than the screen size, will it wrapp correctly?
            This is a great testing app
                        
            This is the end of this textView content
            Here is a Potato
            """
        
        self.textView.backgroundColor = UIColor.green
        self.textView.autoresizingMask = [.flexibleWidth, .flexibleHeight]
        self.textView.textContainer.lineBreakMode = .byWordWrapping
        view.addSubview(self.textView)
        
    }
    
    @objc func handleTap(recognizer: UITapGestureRecognizer) {
        let location: CGPoint = recognizer.location(in: textView)
        let position: CGPoint = CGPoint(x: location.x, y: location.y)
        let tapPosition: UITextPosition = textView.closestPosition(to: position)!
        guard let textRange: UITextRange = textView.tokenizer.rangeEnclosingPosition(tapPosition, with: UITextGranularity.word, inDirection: UITextDirection(rawValue: 1)) else { return }
        
        let tappedWord: String = textView.text(in: textRange) ?? ""
        print("tapped word -> \(tappedWord)")
    }
    
    override func viewWillLayoutSubviews() {
        super.viewWillLayoutSubviews()
        // 若需要textView滚动,直接铺满父视图即可,不需要sizeToFit
        textView.frame = view.bounds
        // 若不需要滚动、希望textView高度自适应内容,替换为下面两行代码即可
        // textView.frame.size.width = view.bounds.width
        // textView.sizeToFit()
    }
}

步骤2:可选优化(自适应高度场景)

如果你不需要textView滚动、希望它的高度跟随内容自适应,在调用WrappedUIViewController的地方添加fixedSize修饰符,告诉SwiftUI纵向自适应高度:

WrappedUIViewController()
    .fixedSize(horizontal: false, vertical: true)
    .padding()

额外注意点

你当前的入口文件中WindowGroup下直接放了两个子视图,默认会以ZStack堆叠,建议放到VStack中避免层级遮挡:

@main
struct testAppApp: App {
    var body: some Scene {
        WindowGroup {
            VStack {
                Text("Test App")
                TestingView()
            }
        }
    }
}

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.10.04 18:09:02