我用UIViewControllerRepresentable创建了这个非常简单的包装:

struct ViewControllerWrapperView: UIViewControllerRepresentable {
    let controller: UIViewController

    func makeUIViewController(context: UIViewControllerRepresentableContext<ViewControllerWrapperView>) -> UIViewController {
        return controller
    }

    func updateUIViewController(_ uiViewController: UIViewController, context: UIViewControllerRepresentableContext<ViewControllerWrapperView>) {}
}

使用它在SwiftUI视图中显示ViewController效果良好:

struct ContentView: View {
    @State private var viewSwitch: Bool = true

    let blueView: ViewControllerWrapperView = {
        let blueViewController = UIViewController()
        blueViewController.view.backgroundColor = .blue
        return ViewControllerWrapperView(controller: blueViewController)
    }()

    let redView: ViewControllerWrapperView = {
        let redViewController = UIViewController()
        redViewController.view.backgroundColor = .red
        return ViewControllerWrapperView(controller: redViewController)
    }()

    var body: some View {
        Button("Switch") { viewSwitch.toggle() }

        if viewSwitch {
            blueView
        } else {
            redView
        }
    }
}

但当我把ViewControllerWrapperView个包裹在AnyView中时,它们就停止正常工作了:

struct ContentView: View {
    @State private var viewSwitch: Bool = true

    let blueView: AnyView = {
        let blueViewController = UIViewController()
        blueViewController.view.backgroundColor = .blue
        return AnyView(ViewControllerWrapperView(controller: blueViewController))
    }()

    let redView: AnyView = {
        let redViewController = UIViewController()
        redViewController.view.backgroundColor = .red
        return AnyView(ViewControllerWrapperView(controller: redViewController))
    }()

    var body: some View {
        Button("Switch") { viewSwitch.toggle() }

        if viewSwitch {
            blueView
        } else {
            redView
        }
    }
}

对于AnyView,点击按钮时视图不会切换.深入研究后,我发现了以下几点:

首次显示视图时,对于这两种情况:

  1. 对于蓝色视图,ViewControllerWrapperView上调用makeUIViewController.
  2. 对于蓝色视图,在ViewControllerWrapperView上调用updateUIViewController,参数uiViewController是蓝色ViewController.

现在,如果没有AnyView,当点击switch 按钮时,UIViewControllerRepresentable的生命周期将按预期执行:

  1. 对于蓝色视图,在ViewControllerWrapperView上调用updateUIViewController,参数uiViewController是蓝色ViewController.
  2. 对于红色视图,ViewControllerWrapperView上调用makeUIViewController.
  3. 对于红色视图,在ViewControllerWrapperView上调用updateUIViewController,参数uiViewController是红色ViewController.
  4. 调用dismantleUIViewController,参数uiViewController是蓝色视图.

ButAnyView当点击switch 按钮时,唯一发生的事情是:

  1. 对于RED视图,在ViewControllerWrapperView上调用updateUIViewController,参数uiViewControllerBLUE ViewController.

我是错过了什么还是这是SwiftUI中的一个bug?

推荐答案

我是错过了什么还是这是SwiftUI中的一个bug?

这不是一个bug,AnyView消除了类型差异,所以渲染body SwiftUI引擎只看到AnyViewAnyView替换为相等的AnyView,所以引擎没有replace个现有视图,只是刷新它(因为状态已更改),导致updateUIViewController调用.一切如期而至.

这就是为什么在清楚了解过程和后果的情况下,使用AnyView应该非常仔细和有意义.

Ios相关问答推荐

快速相机放大手势不能正常工作

带菜单的选取器不适用于Int32,但适用于Int

具有一个参数/参数的泛型类的泛型类

Swift/iOS:泛型错误:协议需要嵌套类型V;你想添加它吗?

Flutter 构建 ios 失败:运行 pod 安装时出错

如何根据条件快速将返回类型设为 LinearGradient 或 AngularGradient?

SwiftUI 我自己的渲染函数的返回类型是什么?

从视图模型中更新 EnvironmentObject

如何在保持纵横比的同时zoom UIView 的内容以适应目标矩形?

通过touch 传递到下面的 UIViews

不变违规:应用程序 AwesomeProject 尚未注册使用静态 jsbundle 为 iOS 设备构建时

无法将NSTaggedPointerString类型的值转换为NSNumber

在原生和 phonegap 之间挣扎,简单的应用需求

UITableView 背景 colored颜色 在 iPad 上总是白色

从 NSUserDefaults 字典 iOS 中删除所有键

正确的领域使用模式/最佳实践?

如何删除UITableView中最后一个单元格的最后一个边框?

ARC - __unsafe_unretained 的含义?

如何为 NSDate 添加一个月?

在 NSUserDefaults 中保存图像?