微信公众号搜"智元新知"关注
微信扫一扫可直接关注哦!

UIScrollView中的SwiftUI View和UIHostingController中断滚动

如何解决UIScrollView中的SwiftUI View和UIHostingController中断滚动

当我添加一个包含SwiftUI视图作为子视图的UIHostingController,然后将该子视图放置在UIScrollView内时,滚动会中断。

在这里我有自己的观点

struct TestHeightView: View {
    let color: UIColor
    
    var body: some View {
        vstack {
            Text("THIS IS MY TEST")
                .frame(height: 90)
        }
            .fixedSize(horizontal: false,vertical: true)
            .background(Color(color))
            .edgesIgnoringSafeArea(.all)
    }
}

然后我有一个带有UIScrollView作为子视图的UIViewController。在UIScrollView内部,有一个UIStackView,它已正确设置,以允许在堆栈高度足够大时加载UIView并滚动浏览它们。这有效。如果要加载40个UILabel,它将可以完美滚动它们。

当我添加一个普通的旧UIView,然后在该容器中添加一个UIHostingController时,就会出现问题。我是这样的:

        let container = UIView()
        container.backgroundColor = color.0
        stackView.insertArrangedSubview(container,at: 0)
        let test = TestHeightView(color: color.1)
        let vc = UIHostingController(rootView: test)
        vc.view.backgroundColor = .clear

        add(child: vc,in: container)

    func add(child: UIViewController,in container: UIView) {
        addChild(child)
        container.addSubview(child.view)
        child.view.translatesAutoresizingMaskIntoConstraints = false

        child.view.topAnchor.constraint(equalTo: container.topAnchor,constant: 0).isActive = true
        child.view.bottomAnchor.constraint(equalTo: container.bottomAnchor,constant: 0).isActive = true
        child.view.leadingAnchor.constraint(equalTo: container.leadingAnchor,constant: 0).isActive = true
        child.view.trailingAnchor.constraint(equalTo: container.trailingAnchor,constant: 0).isActive = true

        child.didMove(toParent: self)

    }

在我的示例中,我添加了三个容器视图/ UIHostingController,然后添加一个UIView(绿色)以演示正在发生的事情。

您可以看到,当我滚动时,所有视图都将在形成间隙时被暂停。发生的情况是,包含的UIView(浅色)正在扩展其高度。一旦高度达到某个值,滚动将继续正常进行,直到下一个容器/ UIHostingController到达顶部并再次开始。

enter image description here

我研究了几种不同的解决方案 .edgesIgnoringSafeArea(.all)

做某事。我将其包含在示例中是因为没有它,问题就完全一样,只是更加刺耳,更难于使用视频来解释。基本上发生了相同的事情,但是没有任何动画,只是看起来UIScrollView已经停止工作,然后又可以工作了

编辑:

添加了另一个UIViewController只是为了确保它一般不是导致问题的子级。不。只有UIHostingControllers可以这样做。 SwiftUI中的内容

解决方法

这是我唯一想出的答案:

我是亚当·贝尔(Adam Bell)在这里https://twitter.com/b3ll/status/1193747288302075906?s=20的推特上找到的

 class EMHostingController<Content> : UIHostingController<Content> where Content : View {
    func fixedSafeAreaInsets() {
        guard let _class = view?.classForCoder else { return }
        
        let safeAreaInsets: @convention(block) (AnyObject) -> UIEdgeInsets = { (sself : AnyObject!) -> UIEdgeInsets in
            return .zero
        }
        
        guard let method = class_getInstanceMethod(_class.self,#selector(getter: UIView.safeAreaInsets)) else { return }
        class_replaceMethod(_class,#selector(getter: UIView.safeAreaInsets),imp_implementationWithBlock(safeAreaInsets),method_getTypeEncoding(method))
        
        let safeAreaLayoutGuide: @convention(block) (AnyObject) ->UILayoutGuide? = { (sself: AnyObject!) -> UILayoutGuide? in
            return nil
        }
        guard let method2 = class_getInstanceMethod(_class.self,#selector(getter: UIView.safeAreaLayoutGuide)) else { return }
        class_replaceMethod(_class,#selector(getter: UIView.safeAreaLayoutGuide),imp_implementationWithBlock(safeAreaLayoutGuide),method_getTypeEncoding(method2))
    }
    
    override var prefersStatusBarHidden: Bool {
        return true
    }
}
,

最近遇到了同样的问题,还要确认安全区域插图正在阻止滚动。我使用 ignoresSafeArea 修饰符

修复了 iOS 14+
    public var body: some View {
        if #available(iOS 14.0,*) {
            contentView
            .ignoresSafeArea()
        } else {
            contentView
        }
    }

版权声明:本文内容由互联网用户自发贡献,该文观点与技术仅代表作者本人。本站仅提供信息存储空间服务,不拥有所有权,不承担相关法律责任。如发现本站有涉嫌侵权/违法违规的内容, 请发送邮件至 dio@foxmail.com 举报,一经查实,本站将立刻删除。