SwiftUI中如何调用其他struct/view内的函数?FSCalendar切换范围示例
问题原因
- 你无法直接在父视图调用
CalendarRepresentable的实例方法:SwiftUI的视图是值类型,你定义的结构只是视图描述,不是实际渲染的运行时实例,调用方法修改的只是结构副本的属性,不会生效。 - 你在
CalendarRepresentable中直接存储FSCalendar实例的写法错误:UIViewRepresentable的UIKit视图实例由makeUIView方法生成、SwiftUI框架管理,你自行存储的实例和屏幕上实际渲染的实例不是同一个,修改它的属性不会有任何效果。
解决方案
通过状态变量绑定的方式同步父子视图的日历范围状态,由状态驱动UI更新,无需直接调用子视图方法。
第一步:修改HomeVC代码
新增控制日历范围的状态变量,绑定到子视图,点击按钮直接修改状态:
struct HomeVC: View { private let navbarcolor = UINavigationBarAppearance() init() { navbarcolor.configureWithOpaqueBackground() navbarcolor.backgroundColor = .systemGreen navbarcolor.titleTextAttributes = [.foregroundColor: UIColor.white] navbarcolor.largeTitleTextAttributes = [.foregroundColor: UIColor.white] UINavigationBar.appearance().standardAppearance = navbarcolor UINavigationBar.appearance().scrollEdgeAppearance = navbarcolor } @State private var selectedDate = Date() // 新增控制日历范围的状态变量 @State private var calendarScope: FSCalendarScope = .week var body: some View { NavigationView{ VStack{ CalendarRepresentable(selectedDate: $selectedDate, scope: $calendarScope) // 高度根据范围动态调整 .frame(height: calendarScope == .week ? 150 : 300) .padding(.top, 15) Spacer() ListView() } .navigationBarTitle("Calendar") .toolbar { Button(action: { // 直接修改状态即可触发UI更新 calendarScope = calendarScope == .month ? .week : .month }) { Text("Toggle") } } } } }
第二步:修改CalendarRepresentable代码
新增范围绑定,在updateUIView方法中同步状态到FSCalendar实例:
struct CalendarRepresentable: UIViewRepresentable{ typealias UIViewType = FSCalendar @Binding var selectedDate: Date // 新增范围绑定属性 @Binding var scope: FSCalendarScope func updateUIView(_ uiView: FSCalendar, context: Context) { // 监听scope状态变化,同步更新FSCalendar的显示范围,加动画更顺滑 if uiView.scope != scope { uiView.setScope(scope, animated: true) } } func makeUIView(context: Context) -> FSCalendar { // 在makeUIView里创建FSCalendar实例,不要存在结构的存储属性里 let calendar = FSCalendar() calendar.delegate = context.coordinator calendar.dataSource = context.coordinator calendar.allowsMultipleSelection = true calendar.scrollDirection = .vertical // 初始值用绑定的scope calendar.scope = scope calendar.appearance.headerTitleFont = UIFont.systemFont(ofSize: 25, weight: UIFont.Weight.heavy) calendar.appearance.weekdayFont = .boldSystemFont(ofSize: 15) calendar.appearance.weekdayTextColor = .black calendar.appearance.selectionColor = .systemGreen calendar.appearance.todayColor = .systemGreen calendar.appearance.caseOptions = [.headerUsesUpperCase, .weekdayUsesUpperCase] calendar.appearance.headerTitleColor = .black return calendar } func makeCoordinator() -> Coordinator { Coordinator(self) } class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource { var parent: CalendarRepresentable var formatter = DateFormatter() init(_ parent: CalendarRepresentable) { self.parent = parent } func calendar(_ calendar: FSCalendar, numberOfEventsFor date: Date) -> Int { return 0 } func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) { formatter.dateFormat = "dd-MM-YYYY" print("Did select == \(formatter.string(from: date))") } func calendar(_ calendar: FSCalendar, didDeselect date: Date, at monthPosition: FSCalendarMonthPosition) { formatter.dateFormat = "dd-MM-YYYY" print("Did de-select == \(formatter.string(from: date))") } } }
内容的提问来源于stack exchange,提问作者razvan2003
相关产品推荐
相关产品推荐

