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

iOS17中Sheet内嵌套TextField导致presentationDetent失效问题

iOS17中带TextField的PageTabViewStyle TabView导致Sheet的presentationDetent失效

问题描述

在iOS16中,设置了.medium或自定义尺寸presentationDetent的Sheet里,嵌入使用PageTabViewStyle的TabView可以正常展示类UIPageView内容(仅存在安全区忽略问题)。但升级到iOS17后,只要TabView内嵌套任意层级的TextField,Sheet就会强制全屏显示,同时出现布局错乱问题;将TextField替换为其他视图(如Color.green)则恢复正常。

复现代码

import SwiftUI

struct ContentView: View {
    
    @State var text = "text"
    @State var showSheet = false
    
    var body: some View {
        VStack {
            Button("SHOW SHEET") {
                showSheet = true
            }
        }
        .sheet(isPresented: $showSheet) {
            TabView {
                TextField("Venue name", text: $text, axis: .vertical)
                TextField("Venue name", text: $text, axis: .vertical)
            }
            .tabViewStyle(PageTabViewStyle())
            .presentationDetents([.medium])
        }
    }
}

测试环境

  • Xcode 15.0 构建
  • iOS17 模拟器/真机可复现
  • iOS16 模拟器/真机运行正常

可行解决方案

目前有两种临时 workaround 可以解决该问题:

1. 给TabView添加明确的高度约束

通过限制TabView的高度,让Sheet能正确识别内容尺寸,避免被TextField的布局需求强制拉伸全屏:

.sheet(isPresented: $showSheet) {
    TabView {
        TextField("Venue name", text: $text, axis: .vertical)
        TextField("Venue name", text: $text, axis: .vertical)
    }
    .tabViewStyle(PageTabViewStyle())
    .frame(height: UIScreen.main.bounds.height * 0.5) // 匹配.medium的大致高度
    .presentationDetents([.medium])
}

2. 使用UIKit的UIPageViewController替代SwiftUI TabView

由于这是iOS17 SwiftUI的底层交互bug,用UIKit组件包装可以规避问题:

struct PageViewController: UIViewControllerRepresentable {
    var controllers: [UIViewController]
    
    func makeUIViewController(context: Context) -> UIPageViewController {
        let pageVC = UIPageViewController(transitionStyle: .scroll, navigationOrientation: .horizontal)
        pageVC.dataSource = context.coordinator
        pageVC.setViewControllers([controllers[0]], direction: .forward, animated: false)
        return pageVC
    }
    
    func updateUIViewController(_ uiViewController: UIPageViewController, context: Context) {}
    
    func makeCoordinator() -> Coordinator {
        Coordinator(self)
    }
    
    class Coordinator: NSObject, UIPageViewControllerDataSource {
        var parent: PageViewController
        
        init(_ parent: PageViewController) {
            self.parent = parent
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerBefore viewController: UIViewController) -> UIViewController? {
            guard let index = parent.controllers.firstIndex(of: viewController) else { return nil }
            return index == 0 ? nil : parent.controllers[index-1]
        }
        
        func pageViewController(_ pageViewController: UIPageViewController, viewControllerAfter viewController: UIViewController) -> UIViewController? {
            guard let index = parent.controllers.firstIndex(of: viewController) else { return nil }
            return index == parent.controllers.count-1 ? nil : parent.controllers[index+1]
        }
    }
}

// 使用示例
.sheet(isPresented: $showSheet) {
    PageViewController(controllers: [
        UIHostingController(rootView: TextField("Venue name", text: $text, axis: .vertical)),
        UIHostingController(rootView: TextField("Venue name", text: $text, axis: .vertical))
    ])
    .presentationDetents([.medium])
}

补充说明:该问题属于iOS17 SwiftUI的已知bug,目前苹果尚未修复,上述方法可临时解决问题,后续可关注iOS版本更新后的修复情况。

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

相关产品推荐
方舟 Agent Plan

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

最近更新时间:2026.07.06 01:10:06