使用UIViewControllerRepresentable(无storyboard)时子视图尺寸布局异常
问题根因
你遇到的UITextView内容超出屏幕无法换行的问题,核心有两个错误点:
CustomUIViewController中的UITextView没有设置初始frame,仅设置autoresizingMask不会自动匹配父视图尺寸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
相关产品推荐
相关产品推荐

