このバグの改修に丸二日ほど費やしたので備忘録として記事にします。
まず最初に環境としては、SwiftUIとFscalendarを使ってアプリの開発をしていました。
バグの詳細
バグの内容はFscalendarで日付の選択をしたときに、選択した日付以外の日付がフラッシュするといった内容のものです。
解決策
原因はupdateUIView()の中でreloadData()が複数回実行されていることでした。
これだけだとソースコードによって状況が違うと思いますので、私のパターンのソースコードの概要を以下に示します。
qiita.swift
struct CalendarDispView : UIViewRepresentable {
func makeUIView(context: Context) -> FSCalendar {
typealias UIViewType = FSCalendar
let fsCalendar = FSCalendar()
fsCalendar.delegate = context.coordinator
fsCalendar.dataSource = context.coordinator
return fsCalendar
}
func updateUIView(_ uiView: FSCalendar, context: Context) {
context.coordinator.updateCalendar(uiView as FSCalendar, with: selectedDate)
// 該当箇所 ここが原因でフラッシュが発生していた
uiView.reloadData()
}
func makeCoordinator() -> Coordinator{
return Coordinator(self)
}
class Coordinator: NSObject, FSCalendarDelegate, FSCalendarDataSource {
var parent:CalendarDispView
init(_ parent:CalendarDispView){
self.parent = parent
}
func calendar(_ calendar: FSCalendar, didSelect date: Date, at monthPosition: FSCalendarMonthPosition) {
parent.selectedDate = date
}
}
}
SwiftUIを使用して、Fscalendarを使用すると大体このようなコードになると思うのですが、私の場合は該当箇所でreloadData()を使っていました。
解決策は、reloadData()を必要な時のみ行うことです。
qiita.swift
func updateUIView(_ uiView: FSCalendar, context: Context) {
context.coordinator.updateCalendar(uiView as FSCalendar, with: selectedDate)
// フラグがtrueであれば、reloadData()が実行されない
if updateCheck.updateFlag { return }
uiView.reloadData()
}
reloadData()が複数回実行されることがなくなり、画面のフラッシュが発生しなくなります。
余談ですが、updateUIView()は構造体のプロパティが更新されるたびに呼び出されるため、reloadData()はFscalendarのイベントマークを更新するために使用していました。
わかりにくい文章ですが、ここまでお読みいただきありがとうございました。