When using the new iOS “chartScrollableAxes” feature annotation that should show on top of the chart view no longer work. When disabling “chartScrollableAxes” everything works again.
Filed as FB12584128
import SwiftUI
import Charts
class ChartDataEntry:Identifiable {
var date:Date
var value:Double
init(date:Date, value: Double) {
self.date=date
self.value=value
}
}
struct ContentView: View {
@State var rawSelectedDate: Date?
var chartData = [ChartDataEntry(date: Date().yesterday.yesterday.yesterday.yesterday.startOfDay, value: 10.0),
ChartDataEntry(date: Date().yesterday.yesterday.yesterday.startOfDay, value: 20.0),
ChartDataEntry(date: Date().yesterday.yesterday.startOfDay, value: 30.0),
ChartDataEntry(date: Date().yesterday.startOfDay, value: 40.0),
ChartDataEntry(date: Date().startOfDay, value: 50.0)]
var body: some View {
VStack {
Chart(chartData) { entry in
BarMark(
x: .value("Day", entry.date, unit: .day),
y: .value("Values", entry.value)
)
if let selectedDate {
RuleMark( x: .value("Selected", selectedDate, unit: .day))
.foregroundStyle(Color.gray.opacity(0.3))
.offset(yStart: -10)
.zIndex(-1)
.annotation(position: .top, spacing: -10,
overflowResolution: .init(
x: .fit(to: .chart),
y: .disabled
)
) {
Text("Longer Sample Text")
}
}
}
.chartScrollableAxes(.horizontal) // <<--- when this is disabled the annotation will be shown correctly
.chartXSelection(value: $rawSelectedDate)
.frame(height: 300)
}
.padding()
}
var selectedDate: Date? {
guard let rawSelectedDate else { return nil }
return chartData.first(where: {
let endOfDay = $0.date.endOfDay
return ($0.date ... endOfDay).contains(rawSelectedDate)
})?.date
}
}
#Preview {
ContentView()
}
extension Date {
var yesterday: Date {
return Calendar.current.date(byAdding: .day, value: -1, to: self)!
}
var startOfDay: Date {
return Calendar.current.startOfDay(for: self)
}
var endOfDay: Date {
var components = DateComponents()
components.day = 1
components.second = -1
return Calendar.current.date(byAdding: components, to: startOfDay)!
}
}