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

SwiftUI MVVM架构下横屏转竖屏适配异常问题求助

iOS 14.0 UIViewRepresentable TextField横竖屏适配问题(MVVM架构下)

问题原因

绑定@State变量时,横竖屏切换会触发SwiftUI视图的body重建,间接促使UIViewRepresentable更新其封装的UIKit TextField布局。但使用ViewModel的@Published属性时,只有当绑定的文本值变化才会调用updateUIView,横竖屏切换时文本未改变,导致UIKit TextField未触发重新布局,宽度停留在横屏状态。

解决方案

方案1:在updateUIView中强制触发布局更新

修改你的UIViewRepresentable实现,确保每次updateUIView被调用时(包括视图环境变化),强制UIKit TextField重新布局:

struct NormalSkyFloatingWithIconTextField: UIViewRepresentable {
    @Binding var text: String
    let placeHolder: String
    let imageName: String
    // 其他参数...
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.placeholder = placeHolder
        textField.translatesAutoresizingMaskIntoConstraints = false
        // 配置图标、样式等
        
        // 设置内容优先级,确保TextField跟随父视图宽度
        textField.setContentHuggingPriority(.defaultLow, for: .horizontal)
        textField.setContentCompressionResistancePriority(.defaultLow, for: .horizontal)
        
        return textField
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
        // 强制触发布局更新
        uiView.setNeedsLayout()
        uiView.layoutIfNeeded()
    }
    
    // 让SwiftUI正确计算视图尺寸
    func sizeThatFits(_ proposal: ProposedViewSize, uiView: UITextField, context: Context) -> CGSize? {
        uiView.sizeThatFits(proposal.replacingUnspecifiedDimensions())
    }
}

方案2:监听横竖屏切换通知,强制更新布局

在UIViewRepresentable中监听设备方向变化通知,直接触发TextField的布局更新:

struct NormalSkyFloatingWithIconTextField: UIViewRepresentable {
    @Binding var text: String
    let placeHolder: String
    let imageName: String
    // 其他参数...
    
    func makeUIView(context: Context) -> UITextField {
        let textField = UITextField()
        textField.placeholder = placeHolder
        textField.translatesAutoresizingMaskIntoConstraints = false
        // 配置其他属性
        
        // 监听方向变化,触发布局
        NotificationCenter.default.addObserver(
            textField,
            selector: #selector(UITextField.layoutIfNeeded),
            name: UIDevice.orientationDidChangeNotification,
            object: nil
        )
        
        return textField
    }
    
    func dismantleUIView(_ uiView: UITextField, coordinator: Coordinator) {
        // 移除通知监听,避免内存泄漏
        NotificationCenter.default.removeObserver(uiView)
    }
    
    func updateUIView(_ uiView: UITextField, context: Context) {
        uiView.text = text
    }
}

方案3:通过ViewModel触发视图更新

如果需要保持MVVM逻辑的一致性,可以在ViewModel中添加一个触发布局的标记,横竖屏切换时切换该标记,促使SwiftUI视图更新:

ViewModel修改:

class SignInViewModel: ObservableObject {
    @Published var emailAddress: String = ""
    @Published var password: String = ""
    @Published private var layoutTrigger = false
    
    func triggerLayoutUpdate() {
        layoutTrigger.toggle()
    }
}

视图修改:

struct SignInView: View {
    @StateObject var viewModel = SignInViewModel()
    
    var body: some View {
        VStack(spacing: 15) {
            NormalSkyFloatingWithIconTextField(
                text: $viewModel.emailAddress,
                placeHolder: "Email Address*",
                imageName: "EmailIcon",
                characterRangeDelegate: self,
                textFieldValue: TextFieldValues.EmailAddress
            )
            .frame(height: 45)
            
            NormalSkyFloatingTextField_Secure(
                text: $viewModel.password,
                placeHolder: "Password*",
                characterRangeDelegate: self,
                textFieldValue: TextFieldValues.PassWord,
                isSecureTextEntry: viewModel.isPasswordVisible
            )
            .frame(height: 45)
        }
        .onReceive(NotificationCenter.default.publisher(for: UIDevice.orientationDidChangeNotification)) { _ in
            viewModel.triggerLayoutUpdate()
        }
    }
}

关键注意点

  • 确保UIKit TextField没有设置固定宽度,必须使用自动布局约束(leading/trailing绑定父视图,或设置内容优先级)。
  • iOS 14中@StateObject是稳定的,但横竖屏切换不会自动触发ViewModel的@Published更新,因此需要手动触发视图布局。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.05 01:34:56