首页 > 解决方案 > SwiftUI 集成 UIKit(iOS 应用)中 @Binding 变量的奇怪行为

问题描述

我正在为我学校的课程开发一个应用程序,显示课程的描述以及显示约会的日历。我决定使用 KVKCalendar 作为日历的库。使用 SwiftUI 开发并将 KVKCalendar 库作为 UIKit 环境,我必须连接两个系统(使用 struct CalendarRepresentable,请参阅代码)。

该应用程序的构造如下:我从内存中加载@ObservedObject保存的对象,将其传递给一些子视图@Binding,以便从课程目录中保存/删除新课程。在视图中所做的所有更改都会在所有其他视图中相应更新,但不幸的是TimetableView,在与 struct 连接的 中没有CalendarRepresentable

问题:我想在保存新课程时更新日历(例如添加到coursestype 的数组中[Courses])。目前该结构CalendarRepresentable正在按预期调用,makeUIView但日历不再更新。特别是保存的课程courses不是不断更新,而是以一种(显然)不一致的方式:在结构的某些函数CalendarRepresentable中确实是最新的,而在其他一些函数(和子类)中则不是。请参阅我显示这些不一致发生的位置和情况的代码。

调用 UIKit-SwiftUI 接口的 View 代码: import SwiftUI import KVKCalendar

struct TimetableView: View {
    @Binding var courses: [Courses]
    let saveAction: () -> Void
    var body: some View {
        CalendarRepresentable(courses: $courses)
            
    }
}

struct TimetableView_Previews: PreviewProvider {
    static var previews: some View {
        TimetableView(courses: .constant(Courses.data), saveAction: {})
    }
}

接口代码:

import SwiftUI
import KVKCalendar
import EventKit

struct CalendarRepresentable: UIViewRepresentable{
    
    @Binding var courses: [Courses]
    
    var events = [Event]()

 
    var calendar: CalendarView = {
        print("Representable has been launched")
        var style = Style()
        //style of the calendar
        //...       
        return CalendarView(frame: UIScreen.main.bounds, style: style)
    }()
    
    
    func updateUIView(_ uiView: CalendarView, context: Context ){
        print("updateUIView has been called. Courses has \(courses.count) elements") // **Here courses has always the correct amount of elements**
        
        calendar.dataSource = context.coordinator
        calendar.delegate = context.coordinator
        calendar.reloadData()
        calendar.reloadInputViews()
        print("updateUIView is finished")
    }
    
    public func passCourses() -> [Courses]{
        print("Called passCourses with courses having \(courses.count) elements") //**Here courses has NOT the corrent amount of elements, i.e. after saving/deleting a course courses.count is different from what is printed in the previous function updateUIView**
        return courses
    }
    
    
    func makeUIView(context: Context) -> CalendarView {
        print("makeUIView has been called")
        calendar.dataSource = context.coordinator
        calendar.delegate = context.coordinator
        calendar.reloadData()
        return calendar
    }
    
    
    
    func makeCoordinator() -> Coordinator {
        print("makeCoordinator")
        return Coordinator(self)
    }
      
    
    
    
    class Coordinator: NSObject, CalendarDelegate, CalendarDataSource {
        var events = [Event]()
        var parent: CalendarRepresentable
        
        func eventsForCalendar(systemEvents: [EKEvent]) -> [Event] {
            print("eventsForCalendar called. In Coordinator \(events.count) events and \(parent.courses.count) courses") //**here courses are again not uptodate to the CalendarRepresentable' courses**
            loadEvents { (events) in
                self.events = events

            }
            return self.events
        }
        
        

        
        init(_ parent: CalendarRepresentable){
            print("Initialize Coordinator")
            self.parent = parent
            super.init()
            
            loadEvents { (events) in
                self.events = events
                self.parent.calendar.reloadData()
            }
        }
        
        func eventsForCalendar() -> [Event] {
            print("eventsForCalendar without parameter")
            return events
        }
        
        
        
        func loadEvents(completion: ([Event]) -> Void) {
            
            var events = [Event]()
        
            print("loadEvents with courses having \(self.parent.courses.count) elements")//**here courses are again not uptodate to the CalendarRepresentable' courses**

            var i: Int=0
            for course in self.parent.passCourses() {

                let isoDateStart = course.startEvent
                let dateStartFormatter = ISO8601DateFormatter()

                let isoDateEnd = course.endEvent
                let dateEndFormatter = ISO8601DateFormatter()
                var event = Event(ID: "\(i)")

                event.start = dateStartFormatter.date(from: isoDateStart)!
                event.end = dateEndFormatter.date(from: isoDateEnd)!
                event.text = course.name

                events.append(event)

                i=i+1
            }
      
            completion(events)
        }
        
        
        
    }
    
}

保存课程(在另一个视图中完成)后控制台输出的示例(明显)不一致:

Representable has been launched
updateUIView has been called. Courses has 4 elements
eventsForCalendar called. In Coordinator 3 events and 3 courses
loadEvents with courses having 3 elements
Called passCourses with courses having 3 elements
updateUIView is finished

有谁知道发生了courses什么?关于我应该如何解决问题的建议?
非常感谢您的时间和帮助!

标签: swiftxcodedata-bindingswiftuiuikit

解决方案


经过广泛的测试后,我发现问题在于,尽管外部结构已更改,但不知何故,协调器已被一位老父母调用。我不确定该行为的内部原因,但无论如何现在应该解决:courses数据现在已成功传递给协调器。courses但是,尽管正确触发发生了变化,但视图仍然不会自行更新updateUIView。任何建议表示赞赏。


推荐阅读