I have a swift program that displays a chart using Chart. The code includes an X Axis Scale parameter but for some reason the last value (right most) on the x axis does not display. It should display Aug 2023. In checking the array used for the x axis labels I find that the last value is Aug 2023. I do not know how to overcome this obstacle. Any assistance will be appreciated. Below is a picture of the bottom of the chart and the code.
struct CustomChartView: View { let vm: SQLDataVM = SQLDataVM.shared let closingValues: [TradingDay] let fundName: String let numYears: Int let maxCloseStruct: TradingDay let maxClose: Double let minCloseStruct: TradingDay let minClose: Double let yIncrment: Double let yAxisValues: [Double] let minTimeStampStruct: TradingDay let minTimeStamp: Date var dateComponent = DateComponents() let maxTimeStampStruct: TradingDay let maxTimeStamp: Date var xAxisValues: [Date] = [] init (fundName: String, numYears: Int) { self.fundName = fundName self.numYears = numYears closingValues = self.vm.QueryDatabase(fundName: fundName, numYears: numYears) maxCloseStruct = self.closingValues.max(by: { (tradingDay1, tradingDay2) -> Bool in return tradingDay1.close < tradingDay2.close })! maxClose = maxCloseStruct.close minCloseStruct = closingValues.min(by: { (tradingDay1, tradingDay2) -> Bool in return tradingDay1.close < tradingDay2.close })! minClose = minCloseStruct.close yIncrment = (maxClose - minClose)/4 yAxisValues = [ minClose, minClose + (1 * yIncrment), minClose + (2 * yIncrment), minClose + (3 * yIncrment), maxClose ] minTimeStampStruct = closingValues.min(by: { (tradingDay1, tradingDay2) -> Bool in return tradingDay1.timeStamp < tradingDay2.timeStamp })! minTimeStamp = minTimeStampStruct.timeStamp maxTimeStampStruct = closingValues.max(by: { (tradingDay1, tradingDay2) -> Bool in return tradingDay1.timeStamp < tradingDay2.timeStamp })! maxTimeStamp = maxTimeStampStruct.timeStamp xAxisValues.append(minTimeStamp) for i in 1...11 { dateComponent.month = i let nextMonth = Calendar.current.date(byAdding: dateComponent, to: minTimeStamp) xAxisValues.append(nextMonth!) } xAxisValues.append(maxTimeStamp) print("\(xAxisValues[12])") // prints 2023-08-04 00:00:00 +0000 } // end init var body: some View { HStack(alignment: .center) { VStack(alignment: .center) { Chart(closingValues, id:\.id) { LineMark( x: .value("Date", $0.timeStamp, unit: .day), y: .value("Closing", $0.close) ) .foregroundStyle(.blue) } // end chart .frame(width: 1000, height: 700, alignment: .center) .chartXAxisLabel(position: .bottom, alignment: .center, spacing: 15) { Text("Date") .font(.custom("Arial", size: 20)) } .chartYAxisLabel(position: .leading, alignment: .center, spacing: 20) { Text("Closing Value") .font(.custom("Arial", size: 20)) } .chartXAxis { AxisMarks(values: xAxisValues) { value in if let date = value.as(Date.self) { AxisValueLabel(horizontalSpacing: -14, verticalSpacing: 10) { VStack(alignment: .leading) { Text(ChartMonthFormatter.string(from: date)) .font(.custom("Arial", size: 14)) Text(ChartYearFormatter.string(from: date)) .font(.custom("Arial", size: 14)) } // end v stack } // end axis label } // end if statement AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) .foregroundStyle(Color.black) AxisTick(centered: true, length: 0, stroke: .none) } } // end chart x axis .chartXScale(domain: [xAxisValues[0], xAxisValues[12]]) .chartYAxis { AxisMarks(position: .leading, values: yAxisValues) { value in AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) .foregroundStyle(Color.black) AxisTick(centered: true, length: 0, stroke: .none) AxisValueLabel(horizontalSpacing: 10) { if let yAxisValue = value.as(Double.self) { let stringValue = String(format: "$%.02f", yAxisValue) Text(stringValue) .font(.custom("Arial", size: 14)) } } } } .chartYScale(domain: [minClose, maxClose]) .chartPlotStyle { plotArea in plotArea.background(.white.opacity(0.9)) .border(.black, width: 1) } // end chart plot style } // end v stack .frame(width: 1200, height: 900, alignment: .center) } // end h stack } // end some view }
After some additional research, it turns out that there are several preset styles for the Axis Marks. The aligned style is what I needed. I added that preset to the Axis Marks contained in .chartXAxis section of code. Problem solved. Below is a pic of the updated x axis labels and the updated code for .chartXAxis.
.chartXAxis { AxisMarks(preset: .aligned, values: xAxisValues) { value in if let date = value.as(Date.self) { AxisValueLabel(horizontalSpacing: -14, verticalSpacing: 10) { VStack(alignment: .leading) { Text(ChartMonthFormatter.string(from: date)) .font(.custom("Arial", size: 14)) Text(ChartYearFormatter.string(from: date)) .font(.custom("Arial", size: 14)) } // end v stack } // end axis label } // end if statement AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) .foregroundStyle(Color.black) AxisTick(centered: true, length: 0, stroke: .none) } } // end chart x axis .chartXScale(domain: [xAxisValues[0], xAxisValues[12]])