我有一个自定义UIViewControllerRepresentable(与布局相关的代码如下所示)。这试图复制本机 SwiftUI ScrollView,除了它从底部滚动,除了顶部。
view: UIView
|
\- scrollView: UIScrollView
|
\- innerView: UIView
|
\- hostingController.view: SwiftUI hosting view
Run Code Online (Sandbox Code Playgroud)
当视图初始化时,这一切都按预期工作。托管视图填充了其内容,并且约束确保滚动视图的contentSize设置正确。
但是,当宿主视图的内容更改时,hostingController.view不会调整大小以适合其内容。
绿色:正如预期的那样,滚动视图与托管视图控制器的大小相匹配。
蓝色:托管视图本身。它保持第一次加载时的大小,并且不会像它应该的那样消耗。
红色:托管视图中的堆栈视图。在此屏幕截图中,内容已添加到堆栈中,导致其展开。结果,您可以看到大小的差异。
滚动视图的内容大小没有明确设置,因为这是由自动布局处理的。
如果有帮助,约束代码如下所示。
class UIBottomScrollViewController<Content: View>: UIViewController, UIScrollViewDelegate {
var hostingController: UIHostingController<Content>! = nil
init(rootView: Content) {
self.hostingController = UIHostingController<Content>(rootView: rootView)
super.init(nibName: nil, bundle: nil)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
var scrollView: UIScrollView = UIScrollView()
var innerView = UIView()
override …Run Code Online (Sandbox Code Playgroud) 更新:2022-09-26
\n此问题已在 iOS 16 上修复。尽管即使使用 iOS 16 SDK 编译项目,该问题在 iOS 15 上仍然存在。
\n原问题:
\n在 iOS 15 上,正在UIHostingController向其托管 SwiftUI 视图添加一些奇怪的额外填充 ( _UIHostingView)。
请参见下面的屏幕截图(蓝色=额外空间,红色=实际视图\xe2\x80\x99s):
\n\n有谁知道为什么会发生这种情况?
\n我已经报告了这个错误,Apple 人员:FB9641883
\nPD:我有一个工作项目重现了我附加到反馈助手问题的问题。如果有人想要的话我也可以上传。
\n我正在尝试使用 UIHostingController 将 SwiftUI 视图添加到 UIKit 视图,并且它显示额外的间距(此示例是为了模拟生产应用程序上的问题而制作的)。这是屏幕截图。

布局概览:
View
UIStackView
UIImageView
UIView(red)
UIHostingController
UIView(blue)
Run Code Online (Sandbox Code Playgroud)
问题: 快速 UI 视图 (UIHostingController) 显示在红色和蓝色视图之间,它在分隔线之后显示额外的间距。间距根据 SwiftUI 视图的大小而变化。
如果我减少行数(Hello World 文本)或减少间距,它似乎工作正常。
这是完整的源代码(https://www.sendspace.com/file/ux0xt7):
ViewController.swift(主视图)
import UIKit
class ViewController: UIViewController {
@IBOutlet weak var mainStackView: UIStackView!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view.
addView()
}
private func addView() {
mainStackView.spacing = 0
mainStackView.alignment = .fill
let imageView = UIImageView()
imageView.image = UIImage(named: "mountain")
imageView.contentMode = .scaleAspectFill
imageView.clipsToBounds = true …Run Code Online (Sandbox Code Playgroud) 我有一个简单的 SwiftUI 视图,其中包含 3 个文本元素:
\nstruct ImageDescriptionView: View {\n var title: String?\n var imageDescription: String?\n var copyright: String?\n\n var body: some View {\n VStack(alignment: .leading) {\n \n if let title = title {\n Text(title)\n .fontWeight(.bold)\n .foregroundColor(.white)\n .frame(maxWidth: .infinity, alignment: .leading)\n }\n \n if let imageDescription = imageDescription {\n Text(imageDescription)\n .foregroundColor(.white)\n .fontWeight(.medium)\n .frame(maxWidth: .infinity, alignment: .leading)\n }\n \n if let copyright = copyright {\n Text(copyright)\n .font(.body)\n .foregroundColor(.white)\n .frame(maxWidth: .infinity, alignment: .leading)\n }\n \n }\n .background(\n Color.blue\n )\n }\n}\nRun Code Online (Sandbox Code Playgroud)\nSwiftUI …
我有 SwiftUI 页面,它是从 UIKit 视图导航的。我想为此页面设置标题,我正在做的是
// code of UIKit view
let controller = UIHostingController(rootView: SwiftUIView())
controller.title = "title"
MyNavigationManager.present(controller)
Run Code Online (Sandbox Code Playgroud)
有没有办法可以访问 SwiftUI 中的托管控制器?
然后我可以写这样的代码
self.hostingController?.title = "title"
我有一个 UIHostingController,它托管一个名为 CatalogView 的 SwiftUI 视图。显示它时,会附加一个环境对象,因此基本上从 UIKit 来看,它显示如下:
let rootCatalogView = CatalogView()
let appState = AppState.get()
let catalogView = UIHostingController(rootView: rootCatalogView.environmentObject(appState))
navigationController.pushViewController(catalogView, animated: true)
Run Code Online (Sandbox Code Playgroud)
现在稍后我需要检查这个 UIHostingController 是否在 navigationController.viewControllers 列表中
type(of:) 显示以下内容,这是有意义的:
UIHostingController<ModifiedContent<CatalogView, _EnvironmentKeyWritingModifier<Optional<AppState>>>>
Run Code Online (Sandbox Code Playgroud)
诸如 vc.self is UIHostingController.Type 或 vc.self is UIHostingController< CatalogView >.Type 之类的东西都返回 false (vc 是 navigationController.viewControllers 的元素
以下显然有效,它返回 true,但是 UIHostingController 初始化中的任何更改都会更改其类型
vc.isKind(of: UIHostingController<ModifiedContent<CatalogView, _EnvironmentKeyWritingModifier<Optional<StoreManager>>>>.self)
Run Code Online (Sandbox Code Playgroud)
我如何检查视图控制器是否属于 UIHostingController 类型?或者至少我如何将控制器投射到 UIHostingController 以便我可以检查其根视图?
我目前正在尝试在 UIViewControllerRepresentable 中实现 UITableViewController,其中单元格的内容再次是 SwiftUI 视图。我不能使用 SwiftUI 列表,因为我想稍后添加一个 UISearchController。
因为我希望能够将自定义 SwiftUI 视图作为每个单元格的内容,所以我不可能在单元格内没有 SwiftUI 视图的情况下做到这一点。
我当前不起作用的代码如下所示:
class SearchableListCell: UITableViewCell {
let contentController: UIViewController
init(withContent content: UIViewController, reuseIdentifier: String) {
self.contentController = content
super.init(style: .default, reuseIdentifier: reuseIdentifier)
self.addSubview(self.contentController.view)
// Tried also
// self.contentView.addSubview(self.contentController.view)
}
required init?(coder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
struct SearchableList: UIViewControllerRepresentable {
let data: [String]
var viewBuilder: (String) -> ContentView
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
func makeUIViewController(context: Context) -> UITableViewController {
return context.coordinator.tableViewController …Run Code Online (Sandbox Code Playgroud) 我正在努力隐藏navigationBar,如果根控制器不是 SwiftUI,它将正确隐藏UIHostingController。
我尝试了以下方法:
navigationController.isNavigationBarHidden = true创建后设置,在viewDidLoad和viewWillAppear。
为's添加.navigationBarHidden(true)和。.navigationBarBackButtonHidden(true)UIHostingControllerrootView
这可能是苹果的一个错误吗?我使用的是 Xcode 11.6。
我所有的尝试在一起:
class LoginController: UINavigationController, ObservableObject
{
static var newAccount: LoginController
{
let controller = LoginController()
let view = LoginViewStep1()
.navigationBarHidden(true)
.navigationBarBackButtonHidden(true)
controller.viewControllers = [UIHostingController(rootView: view)]
controller.isNavigationBarHidden = true
return controller
}
override func viewWillAppear(_ animated: Bool)
{
super.viewWillAppear(animated)
self.isNavigationBarHidden = true
}
override func viewDidLoad()
{
super.viewDidLoad()
self.isNavigationBarHidden = true
}
}
struct LoginViewStep1: View
{ …Run Code Online (Sandbox Code Playgroud) uinavigationbar uinavigationcontroller ios swiftui uihostingcontroller
当我使用 UIHostingController 将新的 SwiftUI.View 推送到现有 UIKit UIViewController 的导航堆栈时,导航栏中标题的动画被破坏。我在 Xcode 12.0 中在一个全新的项目上进行了测试。
仔细观察标题“UIHostingController”。您可以看到该动画与普通的推送动画有何不同,它只是凭空“出现”,看起来很破碎。第二个动画已经从 SwiftUI.NavigationLink 中发生,看起来不错。
如果您想尝试一下,这里是示例项目的链接: https://www.dropbox.com/s/mjkuzhpsb6yvlir/HostingControllerTest.zip ?dl=0
请参阅此 GIF 图像:(如果您看不到 GIF 动画,请在另一个浏览器选项卡中打开)
这是背后的代码:
class ViewController: UIViewController {
private let button = UIButton(frame: .zero)
override func viewDidLoad() {
super.viewDidLoad()
self.title = "UIHostingController Title Test"
self.view.backgroundColor = UIColor.white
self.view.addSubview(self.button)
button.translatesAutoresizingMaskIntoConstraints = false
button.setTitle("Push UIHostingController", for: .normal)
button.addTarget(self, action: #selector(Self.pushVC), for: .touchUpInside)
button.setTitleColor(.blue, for: .normal)
NSLayoutConstraint.activate([
button.centerXAnchor.constraint(equalTo: self.view.centerXAnchor),
button.centerYAnchor.constraint(equalTo: self.view.centerYAnchor),
button.widthAnchor.constraint(equalTo: self.view.widthAnchor),
button.heightAnchor.constraint(equalToConstant: 50)
])
}
@objc private func pushVC() {
let vc …Run Code Online (Sandbox Code Playgroud) 给定: UIHostingController 托管在 UIKit 超级视图中。
时间: Superview 变换在 viewDidAppear 之前修改。在此示例中,向下移动了 200 点。
然后:对超级视图变换的后续更改将不同步。在此示例中,我将其移回原来的位置。尽管 SwiftUI 内容似乎位于正确的位置,但点击注册仍位于原始位置,因此为了点击,我需要点击正在显示的区域下方。(见截图)
Xcode 12.3 - iPhone 8 Sim (iOS 14)
struct ContentView: View {
var body: some View {
Button(action: { print("Testing 123") }, label: {
Text("Button")
})
.padding()
.background(Color.gray)
}
}
class RootVC: UIViewController {
let hostingVC = UIHostingController(rootView: ContentView())
override func viewDidLoad() {
super.viewDidLoad()
hostingVC.view.translatesAutoresizingMaskIntoConstraints = false
view.translatesAutoresizingMaskIntoConstraints = false
addChild(hostingVC)
view.addSubview(hostingVC.view)
hostingVC.didMove(toParent: self)
hostingVC.view.topAnchor.constraint(equalTo: view.topAnchor).isActive = true
hostingVC.view.bottomAnchor.constraint(equalTo: view.bottomAnchor).isActive = true …Run Code Online (Sandbox Code Playgroud) swiftui ×10
ios ×5
swift ×5
ios15 ×2
uikit ×2
autolayout ×1
generics ×1
uitableview ×1
xcode ×1