当使用UIKitRepresentable包装的UIKit对象进行绑定更改时,如何调用方法?

问题描述

这是视图层次结构的顶部。有两个对象SUIScrollHistory,它们是UIKit PageViewController周围的UIViewControllerRepresentable包装器。还有一个DateField,它是一个具有自定义inputView的UIKit TextField的UIViewRepresentable包装器。这两个对象都具有@Binding var date: Date。绑定仅在UITextField代码内部更新,而不会在UIViewRepresentable和UIViewController可表示外部传播。当Bindind<Date>更改时,我需要在两个对象上调用一个方法。有什么建议吗?

TestUI

import SwiftUI

struct TestUI: View
{
    @State var date: Date = Date() {
        didSet {
            print("Tabs date didSet")
        }
    }
    
    var body: some View {
        NavigationView {
            SUIScrollHistory(date: $date)
                .edgesIgnoringSafeArea(.top)
                .navigationBarTitle("History")
                .navigationBarItems(trailing: DateField(date: $date))
        }
    }
}

这是包装在UIViewControllerRepresentable中的ScrollView。

import UIKit
import SwiftUI
import CoreData

final class SUIScrollHistory: UIViewControllerRepresentable
{
    @Binding var date: Date {
        willSet {
            print("SUI scroll history willSet:")
            print("scroll to appropriate pg")
            print("NOT CALLED")
        }
    }
    
    init(date: Binding<Date>) {
        self._date = date
    }
    
    func makeUIViewController(context: Context) -> ScrollHistory {
        return ScrollHistory(date: _date)
    }
    
    func updateUIViewController(_ uiViewController: ScrollHistory,context: Context) {
        //test
    }
}

import UIKit
import SwiftUI
import CoreData

class ScrollHistory: UIPageViewController,UIPageViewControllerDelegate,UIPageViewControllerDataSource
{
    @Binding var date: Date {
        willSet {
            scrollTo(newDate: newValue)
            print("scroll history willSet")
            print("scroll to appropriate pg")
            print("NOT CALLED")
        }
    }
    
    init(date: Binding<Date>) {
        self._date = date
        super.init(transitionStyle: .scroll,navigationorientation: .horizontal,options: nil)
        self.setViewControllers( [ UIHostingController(rootView: Rectangle().overlay(Color.blue)) ],direction: .forward,animated: true,completion: nil)
        self.delegate = self
        self.dataSource = self
        self.view.isUserInteractionEnabled = true
        self.title = "Mon,Aug 17"
    }
    
    required init?(coder: NSCoder) { fatalError() }
    
    func scrollTo(newDate: Date) {
        if newDate > date {  //Slide the PageVC left if date > currentDay
            //let nextDay = date.nextDay()
            
            let edibleJournalTVC = UIHostingController(rootView: Text("inject date"))
            self.setViewControllers([edibleJournalTVC],completion: nil)
        }
        if newDate < date {  //Slide the PageVC right if date < currentDay
            //let prevIoUsDay = date.prevIoUsDay()
            let edibleJournalTVC = UIHostingController(rootView: Text("inject date")) //self.fdPg(date: date) //FIXME: = FoodPage(date: prevIoUsDay)
            
            self.setViewControllers([edibleJournalTVC],direction: .reverse,completion: nil)
        }
        self.date = newDate //Todo: Does this loop infinitely?
    }
    
    func pageViewController(_ pageViewController: UIPageViewController,didFinishAnimating finished: Bool,prevIoUsViewControllers: [UIViewController],transitionCompleted completed: Bool) {
        
        //update DateField
    }
    
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerBefore viewController: UIViewController) -> UIViewController? {
        let foodPage = UIHostingController(rootView: Text("inject date")) //FIXME: Binding<Date>(prevIoUsDay)))
        return foodPage
    }
    
    func pageViewController(_ pageViewController: UIPageViewController,viewControllerAfter viewController: UIViewController) -> UIViewController? {
        let foodPage = UIHostingController(rootView: Text("inject date")) //FIXME nextDay))
        return foodPage
    }
}

这是包装在UIViewRepresentable中的DateField。

import SwiftUI
import UIKit

struct DateField: UIViewRepresentable
{
    @Binding var date: Date {
        willSet {
            print("DateField willSet")
            print("NOT CALLED")
        }
        didSet {
            print("DateField didSet")
            print("NOT CALLED")
        }
    }
    private let format: DateFormatter
    
    
    init(date: Binding<Date>,format: DateFormatter = YMDFormat()) {
        self._date = date
        self.format = format
    }
    
    func makeUIView(context: UIViewRepresentableContext<DateField>) -> UITextField {
        let tf = DateTextField(date: $date)  //FIXME: not injected bcs it's a wrapper
        print("makeUIView")
        return tf
    }
    
    func updateUIView(_ uiView: UITextField,context: UIViewRepresentableContext<DateField>) {
        print("updateUIView")
        uiView.text = format.string(from: date)
    }
}


import SwiftUI
import UIKit

class DateTextField: UITextField
{
    @Binding var date: Date {
        willSet {
            print("DateTextField Date")
            print("Is Called")
        }
    }
    private lazy var pickDate: UIDatePicker = { return UIDatePicker() }()
    
    init(date: Binding<Date>) {
        self._date = date
        super.init(frame: .zero)
        self.pickDate.date = date.wrappedValue
        self.pickDate.addTarget(self,action: #selector(dateChanged(_:)),for: .valueChanged)
        self.inputView = pickDate
        self.textColor = .black
    }
    
    required init?(coder: NSCoder) { fatalError() }
    
    @objc func dateChanged(_ sender: UIDatePicker) {
        self.date = sender.date
    }
}


import Foundation

class YMDFormat: DateFormatter
{
    override init() {
        super.init()
        dateFormat = "yyyy-MM-dd"
    }
    
    required init?(coder: NSCoder) { fatalError() }
}

解决方法

暂无找到可以解决该程序问题的有效方法,小编努力寻找整理中!

如果你已经找到好的解决方法,欢迎将解决方案带上本链接一起发送给小编。

小编邮箱:dio#foxmail.com (将#修改为@)