コガネブログ

平日更新を目標に Unity や C#、Visual Studio、ReSharper などのゲーム開発アレコレを書いていきます

【SwiftUI】UIViewRepresentable でラップした FSCalendar を ObservableObject や Published で更新する例

ソースコード

import SwiftUI

class DayData: ObservableObject {
    @Published var date = "2022-06-01"
    @Published var count = 0
}

struct ContentView: View {
    @ObservedObject var dayData = DayData()
    
    var body: some View {
        VStack {
            CalendarView(dayData: Binding.constant(dayData))
                .frame(height: 432)
            Button(action: {
                dayData.count += 1
            }) {
                Text("Count Up: \(dayData.count)")
            }
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}
import SwiftUI
import FSCalendar
import UIKit

struct CalendarView: UIViewRepresentable {
    @Binding var dayData: DayData
    
    func makeUIView(context: Context) -> FSCalendar {
        
        typealias UIViewType = FSCalendar
        
        let fsCalendar = FSCalendar()
        
        fsCalendar.delegate = context.coordinator
        fsCalendar.dataSource = context.coordinator
        fsCalendar.appearance.headerDateFormat = "yyyy年MM月"
        
        return fsCalendar
    }
    
    func updateUIView(_ uiView: FSCalendar, context: Context) {
        uiView.reloadData()
    }
    
    func makeCoordinator() -> Coordinator{
        return Coordinator(self)
    }
    
    // https://stackoverflow.com/questions/72116719/swift-fscalendar-how-to-insert-image-in-date
    class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
        var parent:CalendarView
        let dateFormatter = DateFormatter()
        
        init(_ parent:CalendarView){
            self.parent = parent
        }
        
        func calendar(_ calendar: FSCalendar, imageFor date: Date) -> UIImage? {
            dateFormatter.dateFormat = "yyyy-MM-dd"
            guard let eventDate = dateFormatter.date(from: parent.dayData.date) else {
                return nil
            }
            
            if date.compare(eventDate) == .orderedSame{
                return UIImage(systemName: "\(parent.dayData.count).circle.fill")
            }
            return nil
        }
    }
}

updateUIView で uiView.reloadData() を実行すると
ObservableObject や Published で更新できるようになる