Ios SwiftUI列表中的滚动信息-UIViewRepresentable UIScrollView列表绑定不总是与SwiftUI一起工作
我试图通过使用UIViewRepresentable包装/注入UIScrollView来观察/获取SwiftUI的一些列表滚动属性 我的绑定行为不一致 按下按钮并根据按钮是否在父视图和子视图中更改值会产生不同的结果。Ios SwiftUI列表中的滚动信息-UIViewRepresentable UIScrollView列表绑定不总是与SwiftUI一起工作,ios,objective-c,swift,swift3,swiftui,Ios,Objective C,Swift,Swift3,Swiftui,我试图通过使用UIViewRepresentable包装/注入UIScrollView来观察/获取SwiftUI的一些列表滚动属性 我的绑定行为不一致 按下按钮并根据按钮是否在父视图和子视图中更改值会产生不同的结果。 我的ObserveObject ScrollInfo类和UIViewRepresentable的绑定开始时很好,但随后会中断,除非整个屏幕被刷新并使UIView再次运行(如更改为其他选项卡) 有没有办法强制UIViewRepresentable在绑定更新时再次运行makeUIVie
我的ObserveObject ScrollInfo类和UIViewRepresentable的绑定开始时很好,但随后会中断,除非整个屏幕被刷新并使UIView再次运行(如更改为其他选项卡) 有没有办法强制UIViewRepresentable在绑定更新时再次运行makeUIView?还是能解决这个问题?
我希望ISSCROLING值能够随时更新和工作 我设置了一个测试,如果用户向下拖动scrollview,则将圆圈的颜色更改为红色。它最初工作,但如果我从父视图中的ObserveObject更新一个值,它就会停止。
来自下面代码的测试截图
编辑-解决方案 我无法让它与ObserveObject或EnvironmentObject一起工作,但我能够让它与@State和@Binding一起工作,尽管返回的信息数量有限。(ScrollInfo仍然存在,仅用于测试更改父ObserveObject) 希望这对其他人有帮助
import SwiftUI
struct TestView: View {
@State var isScrolling:Bool = false;
var body: some View {
VStack
{
Button(action:{
self.scrollInfo.contentLoaded.toggle()
}) {
Text("REFRESH")
}
List{
VStack {
VStack{
Text("isScrolling")
Text(String(self.isScrolling))
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
} .padding(.bottom,620).padding(.top,20).background( ListScrollingHelper(isScrolling: self.$isScrolling))
}.padding(.top,4)
}
}
}
extension UIView {
func enclosingScrollView() -> UIScrollView? {
var next: UIView? = self
repeat {
next = next?.superview
if let scrollview = next as? UIScrollView {
return scrollview
}
} while next != nil
return nil
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
final class ListScrollingHelper: UIViewRepresentable {
@Binding var isScrolling:Bool
private var scrollView: UIScrollView?
init(isScrolling:Binding<Bool>)
{
self._isScrolling = isScrolling
}
func makeUIView(context: Context) -> UIView {
return UIView()
}
func catchScrollView(for view: UIView) {
if nil == scrollView {
scrollView = view.enclosingScrollView()
}
}
func updateUIView(_ uiView: UIView, context: Context) {
catchScrollView(for: uiView)
if(scrollView != nil)
{
scrollView!.delegate = context.coordinator
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject,UIScrollViewDelegate {
var parent: ListScrollingHelper
init(_ listScrollingHelper: ListScrollingHelper) {
self.parent = listScrollingHelper
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if(!self.parent.isScrolling)
{
self.parent.isScrolling = true
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if(self.parent.isScrolling && !decelerate)
{
self.parent.isScrolling = false
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if(self.parent.isScrolling)
{
self.parent.isScrolling = false
}
}
deinit
{
}
}
deinit {
}
}
class ScrollInfo: ObservableObject {
@Published var isScrolling:Bool = false
@Published var text:String = "Blank"
@Published var contentLoaded:Bool = false
}
导入快捷界面
结构测试视图:视图{
@状态变量isScrolling:Bool=false;
var body:一些观点{
VStack
{
按钮(操作:{
self.scrollInfo.contentLoaded.toggle()文件
}) {
文本(“刷新”)
}
名单{
VStack{
VStack{
文本(“IsCrolling”)
文本(字符串(self.isScrolling))
圆圈().边框(宽:50,高:50).前底色(self.isScrolling?.red:.绿色)
}
VStack{
文本(self.scrollInfo.Text)
文本(self.test1)
圆圈().边框(宽:50,高:50).前底色(self.isScrolling?.red:.绿色)
}
VStack{
文本(self.scrollInfo.Text)
文本(self.test1)
圆圈().边框(宽:50,高:50).前底色(self.isScrolling?.red:.绿色)
}
VStack{
文本(self.scrollInfo.Text)
文本(self.test1)
圆圈().边框(宽:50,高:50).前底色(self.isScrolling?.red:.绿色)
}
}.padding(.bottom,620)。padding(.top,20)。背景(ListScrollingHelper(isScrolling:self.$isScrolling))
}.padding(.top,4)
}
}
}
扩展UIView{
func enclosingScrollView()->UIScrollView{
var next:UIView?=self
重复{
下一个=下一个?.superview
如果让scrollview=next as?UIScrollView{
返回滚动视图
}
}而下一个!=零
归零
}
}
结构测试视图\u预览:PreviewProvider{
静态var预览:一些视图{
TestView()
}
}
最终类列表ScrollingHelper:UIViewRepresentable{
@绑定变量为crolling:Bool
私有var scrollView:UIScrollView?
初始(isScrolling:绑定)
{
自我保护=自我保护
}
func makeUIView(上下文:context)->UIView{
返回UIView()
}
func catchScrollView(用于视图:UIView){
如果nil==scrollView{
scrollView=view.EnclosuringScrollView()
}
}
func updateUIView(uiView:uiView,context:context){
catchScrollView(用于:uiView)
如果(滚动视图!=nil)
{
scrollView!.delegate=context.coordinator
}
}
func makeCoordinator()->Coordinator{
协调员(自我)
}
类协调器:NSObject、UIScrollViewDelegate{
变量父项:ListScrollingHelper
init(uuListScrollingHelper:listScrollingHelper){
self.parent=listScrollingHelper
}
func scrollView将开始刷新(scrollView:UIScrollView){
如果(!self.parent.IsCrolling)
{
self.parent.isScrolling=true
}
}
func ScrollViewDiEndDraging(scrollView:UIScrollView,将减速减速:Bool){
if(self.parent.iscrowling&&!减速)
{
self.parent.isScrolling=false
}
}
func ScrollViewDiEndDecelling(scrollView:UIScrollView){
if(自、父、IsCrolling)
{
self.parent.isScrolling=false
}
}
脱硝
{
}
}
脱硝{
}
}
类ScrollInfo:ObservableObject{
@已发布变量isScrolling:Bool=false
@已发布的变量文本:String=“Blank”
@已发布的变量contentLoaded:Bool=false
}
中的解决方案应该很有帮助。是的,我就是从那里开始构建的。我最终无法使用我的代码,因为实际的应用程序中有列表
import SwiftUI
struct TestView: View {
@State var isScrolling:Bool = false;
var body: some View {
VStack
{
Button(action:{
self.scrollInfo.contentLoaded.toggle()
}) {
Text("REFRESH")
}
List{
VStack {
VStack{
Text("isScrolling")
Text(String(self.isScrolling))
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
VStack{
Text(self.scrollInfo.text)
Text(self.test1)
Circle().frame(width:50,height:50).foregroundColor(self.isScrolling ? .red : .green)
}
} .padding(.bottom,620).padding(.top,20).background( ListScrollingHelper(isScrolling: self.$isScrolling))
}.padding(.top,4)
}
}
}
extension UIView {
func enclosingScrollView() -> UIScrollView? {
var next: UIView? = self
repeat {
next = next?.superview
if let scrollview = next as? UIScrollView {
return scrollview
}
} while next != nil
return nil
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
TestView()
}
}
final class ListScrollingHelper: UIViewRepresentable {
@Binding var isScrolling:Bool
private var scrollView: UIScrollView?
init(isScrolling:Binding<Bool>)
{
self._isScrolling = isScrolling
}
func makeUIView(context: Context) -> UIView {
return UIView()
}
func catchScrollView(for view: UIView) {
if nil == scrollView {
scrollView = view.enclosingScrollView()
}
}
func updateUIView(_ uiView: UIView, context: Context) {
catchScrollView(for: uiView)
if(scrollView != nil)
{
scrollView!.delegate = context.coordinator
}
}
func makeCoordinator() -> Coordinator {
Coordinator(self)
}
class Coordinator: NSObject,UIScrollViewDelegate {
var parent: ListScrollingHelper
init(_ listScrollingHelper: ListScrollingHelper) {
self.parent = listScrollingHelper
}
func scrollViewWillBeginDragging(_ scrollView: UIScrollView) {
if(!self.parent.isScrolling)
{
self.parent.isScrolling = true
}
}
func scrollViewDidEndDragging(_ scrollView: UIScrollView, willDecelerate decelerate: Bool) {
if(self.parent.isScrolling && !decelerate)
{
self.parent.isScrolling = false
}
}
func scrollViewDidEndDecelerating(_ scrollView: UIScrollView) {
if(self.parent.isScrolling)
{
self.parent.isScrolling = false
}
}
deinit
{
}
}
deinit {
}
}
class ScrollInfo: ObservableObject {
@Published var isScrolling:Bool = false
@Published var text:String = "Blank"
@Published var contentLoaded:Bool = false
}