Swift Charts

RSS for tag

Visualize data with highly customizable charts across all Apple platforms using the compositional syntax of SwifUI.

Swift Charts Documentation

Posts under Swift Charts tag

53 Posts
Sort by:
Post not yet marked as solved
1 Replies
962 Views
Hi there, When using the AxisValueLabel in Swift Charts, the moment you add centered: true, the month or day on the right disappears. This has been a bug for over five months since I looked through other developer forums and they had the same issue. AxisValueLabel(format: .dateTime.weekday(), centered: true) leads to the following view: Now if we remove the centered: true, saturday will appear. It is probably a spacing issue, but since these are modifiers provided by Apple, it should do it correctly, right? If I am missing something and this is by desing, please enlighten me. Best Til
Posted Last updated
.
Post not yet marked as solved
4 Replies
1.8k Views
In a Swift Chart that listens for drag gestures in order to display a RuleMark with an annotation, the y-axis scale changes while dragging which causes the entire chart to jump. I have a small code example that demonstrates this at https://github.com/mvolkmann/ChartJump. See the two screenshots there.
Posted
by mvolkmann.
Last updated
.
Post not yet marked as solved
9 Replies
3.1k Views
I'm experiencing a problem where my NavigationLink hangs when on the same view as a somewhat complicated chart. Additional Context: My Swift Chart has a fair number of data points (2000+). I'm also doing custom modification using the .chartYAxis modifier. .chartYAxis { AxisMarks(values: .stride(by: 1)) { value in            AxisGridLine()            AxisTick()            // In my app I also put a value label here, but that doesn't seem to be the thing in particular that slows this down.      } } When I do this modifier along with having a big set of data points, if I have a NavigationLink elsewhere on the same view, it hangs when I press the NavigationLink. Notably, if I remove this modifier, it doesn't hang. (By hang I mean it takes about 1s to navigate to the next view). Here's a slightly contrived example that mirrors my actual app, minus the generation of data points: import SwiftUI import Charts struct ContentView: View {     var body: some View {         NavigationStack {             NavigationLink(value: "NavigationKey") {                 Text("Link")             }             ChartView()             Text("Main View")                 .navigationDestination(for: String.self) { path in                     SomeView()                 }         }     } } struct ChartView: View {     var chartXY: [(x: Double, y: Double)] {         var entries: [(x: Double, y: Double)] = []         for i in 0..<2500             let y = Double.random(in: 0..<8000)             entries.append((x: Double(i), y: y))         }         return entries     }          var body: some View {         List {             Chart {                 ForEach(chartXY, id: \.x) {                     LineMark(x: .value("x", $0.x), y: .value("y", $0.y))                 }             }             .frame(minHeight: 100.0)             // Commenting out this block == no hang             .chartYAxis {                 AxisMarks(values: .stride(by: 1)) { value in                     AxisGridLine()                     AxisTick()                     // In my app I also put a value label here, but that doesn't seem to be the thing in particular that slows this down.                 }             }         }     } } struct SomeView: View {     var body: some View {         Text("hello")     } } Presumably, given commenting out the block solves the problem, SwiftUI is preparing some large amounts of AxisMarks/GridLines/AxisTicks for the view transition. Is there someway for me to indicate that it shouldn't do that to prevent this problem? Or is there some other reason this would be hanging?
Posted Last updated
.
Post not yet marked as solved
0 Replies
616 Views
Does anyone know of to get the currently visible data items in chart (e.g. BarMarks) on iOS 17 when using chartScrollableAxes. From the WWDC23 video of session "Explore pie charts and interactivity in Swift Charts" at time 8:18 you see that the "Total sales" lists the visible time frame (e.g. May 4 - June 4, 2023) and a few seconds late when the chart scrolls the values do update.
Posted
by Besti.
Last updated
.
Post not yet marked as solved
2 Replies
457 Views
When using charts framework to make a Bar Chart after creating my fake data and creating the chart in the contentView no x or y axis contents appeared I was following a tutorial and they appeared with him any one can help Bar Chart import SwiftUI import Charts struct Items : Identifiable { var id = UUID() let type : String let value : Double } struct ContentView: View { let items : [Items] = [ Items(type: "Medical", value: 10000), Items(type: "Engeneering", value: 5000), Items(type: "singing", value: 15000), Items(type: "pilot", value: 1000), Items(type: "athlete", value: 18000), ] ![]("https://developer.apple.com/forums/content/attachment/73dd58fb-2753-4d65-be30-ad4ae7ebb1be" "title=Screen Shot 2023-07-10 at 6.19.04 AM.png;width=854;height=1598") var body: some View { NavigationView{ ScrollView{ Chart(items){item in BarMark( x: .value("Job", item.type), y: .value("salary", item.value) ) .foregroundStyle(.brown) .cornerRadius(10) } .frame(height: 200) .padding() } .navigationTitle("Charts") } }
Posted Last updated
.
Post not yet marked as solved
0 Replies
832 Views
@Apple: Would it be possible to get the source of the Sample app shown in WWDC 2023 session “Explore pie charts and interactivity in Swift Charts” https://developer.apple.com/wwdc23/10037 In particular I’m interested in learning how to get the dates of currently be viewed bar marks in a scroll view. You can see that in the video at 9:12 on the iPhone screen showing the demo app.
Posted
by Besti.
Last updated
.
Post not yet marked as solved
0 Replies
891 Views
I like to have a scrollable chart with chartXSelection. How can that be accomplished? As soon as I have .chartXSelection the chart doesn't really scroll any more. I'm looking for some sort of delayed chartXSelection gesture, where the chartXSelection kicks in after a short delay of 1-2 seconds. The Apple Heath App does support this very nicely.
Posted
by Besti.
Last updated
.
Post not yet marked as solved
2 Replies
1.2k Views
I have a scrollable barmark chart that is introduced in iOS 17 but I have problem to set the initial horizontal scroll position. I want to use the ".chartScrollPosition(initialX:..." but initialX needs to be of type Plottable I can't understand how I can define that. Here is an example, I want it to scroll to the far right (newest days). I show seven days at a time. import SwiftUI import Charts struct ContentView: View { let stepDays: [StepDay] = [ StepDay(date: Calendar.current.date(byAdding: .day, value: -10, to: Date())!, steps: 12342), StepDay(date: Calendar.current.date(byAdding: .day, value: -9, to: Date())!, steps: 8345), StepDay(date: Calendar.current.date(byAdding: .day, value: -8, to: Date())!, steps: 7656), StepDay(date: Calendar.current.date(byAdding: .day, value: -7, to: Date())!, steps: 4564), StepDay(date: Calendar.current.date(byAdding: .day, value: -6, to: Date())!, steps: 2344), StepDay(date: Calendar.current.date(byAdding: .day, value: -5, to: Date())!, steps: 7654), StepDay(date: Calendar.current.date(byAdding: .day, value: -4, to: Date())!, steps: 4532), StepDay(date: Calendar.current.date(byAdding: .day, value: -3, to: Date())!, steps: 6788), StepDay(date: Calendar.current.date(byAdding: .day, value: -2, to: Date())!, steps: 4567), StepDay(date: Calendar.current.date(byAdding: .day, value: -1, to: Date())!, steps: 5678), StepDay(date: Date(), steps: 1234)] var body: some View { Chart { ForEach(stepDays, id: \.date) { stepDay in BarMark( x: .value("Day", stepDay.weekDay), y: .value("Steps", stepDay.steps) ) } } .chartScrollableAxes(.horizontal) .chartXVisibleDomain(length: 7) // .chartScrollPosition(initialX: <#T##Plottable#>) // I want to scroll to far right so that I can see the newest days, can I do that with chartScrollPosition(initialX:... ??? } } struct StepDay { var date: Date var weekDay: String var steps: Int init(date: Date, steps: Int) { let dateFormatter = DateFormatter() dateFormatter.dateFormat = "d/M" self.date = date self.weekDay = dateFormatter.string(from: date) self.steps = steps } }
Posted Last updated
.
Post not yet marked as solved
0 Replies
471 Views
I have created Swift Charts using Ready Made Data Like below static let last12Months = [ (month: date(year: 2022, month: 6), KW: 3952, dailyAverage: 127, dailyMin: 95, dailyMax: 345), (month: date(year: 2022, month: 7), KW: 8322, dailyAverage: 124, dailyMin: 55, dailyMax: 255), (month: date(year: 2022, month: 8), KW: 2952, dailyAverage: 245, dailyMin: 99, dailyMax: 673), (month: date(year: 2022, month: 9), KW: 3352, dailyAverage: 875, dailyMin: 92, dailyMax: 623), (month: date(year: 2022, month: 10), KW: 3252, dailyAverage: 257,dailyMin: 55, dailyMax: 675), (month: date(year: 2022, month: 11), KW: 3232, dailyAverage: 537,dailyMin: 65, dailyMax: 643), (month: date(year: 2022, month: 12), KW: 9871, dailyAverage: 253,dailyMin: 25, dailyMax: 987), (month: date(year: 2023, month: 1), KW: 8623, dailyAverage: 235, dailyMin: 96, dailyMax: 353), (month: date(year: 2023, month: 2), KW: 7612, dailyAverage: 276, dailyMin: 64, dailyMax: 765), (month: date(year: 2023, month: 3), KW: 2335, dailyAverage: 978, dailyMin: 36, dailyMax: 456), (month: date(year: 2023, month: 4), KW: 9087, dailyAverage: 667, dailyMin: 63, dailyMax: 675), (month: date(year: 2023, month: 5), KW: 2823, dailyAverage: 865, dailyMin: 100, dailyMax: 765), (month: date(year: 2023, month: 6), KW: 9762, dailyAverage: 544, dailyMin: 36, dailyMax: 999), ] `but now I want to create same charts with real world reading like Health App. For example aim taking the sensor value through bluetooth, I can show the reading from sensor to app but how can I store the data for months and show them in Charts Any Ideas where am I lagging`
Posted Last updated
.
Post not yet marked as solved
0 Replies
319 Views
Hi all, I'm trying to implement a dynamic chart to log weight over time for an espresso app. I've been struggling to find recourses to plot a continuously updating chart so, I'm currently using a timer to append new data to an array and then redraw the chart. Thats all working fine but, I'm getting 1GB< Memory usage after appending only 15 seconds worth of data at 10 datapoints/second. I would love to find a way to optimise this. Here is my main View Controller. There is some connect to scale stuff in there but, for testing I'm bypassing the scale data. All I'm doing is upon opening the view I'm: starting a counter, converting the counter to a min, sec ,millisec value, appending time information from my counter to the array, appending a random value from 1-10 as my mock weight data to the array, calling my chart view because it lives in a different file import UIKit import AcaiaSDK import SwiftUI import Charts var cList: [weight_time] = [] var timer: Timer! var count: Double! var timeInDouble: Double! var isCounting: Bool! var hideview: Bool = true class ChartVC: UIViewController { override func viewDidLoad() { super.viewDidLoad() } override func viewWillAppear(_ animated: Bool) { } override func viewDidAppear(_ animated: Bool) { timeInDouble = 0 count = 0 createTimer() print("Timer Started") isCounting = true } override func viewWillDisappear(_ animated: Bool) { if isCounting == true { timer.invalidate() print("Timer Stopped") isCounting == false } } func createTimer(){ cList.removeAll() timer = Timer.scheduledTimer(timeInterval: 0.1, target: self, selector: #selector(counter), userInfo: nil, repeats: true) } @objc func counter(){ count += 0.1 let minutes = Int(count) / 60 % 60 let seconds = Int(count) % 60 let mil = Int(count*10) % 10 //print(mil) let m_s = String(format:"%02i.%02i%01i", minutes, seconds,mil) timeInDouble = Double(m_s) //if mil == 1 { fillChart() // } print(timeInDouble!) } func fillChart(){ cList.append(weight_time(weight: Float(.random(in: 1...10)) , time: timeInDouble)) setupView() } // MARK: test Chart import func setupView(){ let controller = UIHostingController(rootView: chartvalues()) guard let chartView = controller.view else{ return } view.addSubview(chartView) controller.view.isHidden = false chartView.snp.makeConstraints{make in make.centerY.equalToSuperview() make.leading.equalToSuperview().offset(15) make.trailing.equalToSuperview().inset(15) make.height.equalTo(300) } } } import Charts import Foundation import AcaiaSDK import UIKit struct weight_time:Identifiable { let id = UUID() let weight: Float let time: Double } struct chartvalues: View{ let testList = [ weight_time( weight: 0.0, time: 0.5), weight_time(weight: 0.5, time: 1.0), weight_time(weight: 1.2, time: 1.5), weight_time(weight: 1.72, time: 2.0), weight_time(weight: 2.8, time: 2.5), weight_time(weight: 3.0, time: 3.0), weight_time(weight: 4.25, time: 3.5), weight_time(weight: 4.94, time: 4.0), weight_time(weight: 5.62, time: 4.5), weight_time(weight: 6.6, time: 5.0) ] var body: some View{ if cList != nil { Chart(cList){ weight_time in LineMark( x: .value("Time", weight_time.time), y: .value("Weight", weight_time.weight) ).foregroundStyle(.red) } } //Text(cList) } }```
Posted
by CasualRei.
Last updated
.
Post not yet marked as solved
4 Replies
1.9k Views
I have a dataset I want to have split between past/historic data and future/predicted data. The values for the predicted data take the last value from pastData and apply a decay function to show how much of something is left. I have the data split into two arrays (sampleData_History and sampleData_Future); I have also attempted this with the data combined (sampleData) and tried a conditional in the .foregroundStyle property. Chart { ForEach(sampleData_History) { item in RuleMark(x: .value("Now", Date.now, unit: .hour)).foregroundStyle(.orange) LineMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ) .foregroundStyle(Color.blue) AreaMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ).foregroundStyle(Color.teal.opacity(0.2)) } ForEach(sampleData_Future) { item in LineMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ) .foregroundStyle(Color.red) AreaMark( x: .value("time", item.date, unit: .hour), y: .value("mg", item.amount) ).foregroundStyle(Color.red.opacity(0.2)) } } The above code yields the screenshot below. In the ideal case, I'd like to have everything AFTER the RuleMark line be a different color. Am I missing something? Where might I look to figure this out? EDIT: I have also tried separating them into series to no avail
Posted
by zt01zg.
Last updated
.
Post marked as solved
3 Replies
1.5k Views
I have a view that displays a chart based on an array. Each element in the array is all of the attributes associated with a core data entity. The data is properly displayed. I would like to animate the rendering of the charts data but cannot seem to figure out how to do it. If someone could point me in the right direction it would be appreciated. Below is the code. struct ClosingValuesChart: View { @State private var selectedDate: Date? = nil @State private var selectedClose: Float? = nil @State private var xAxisLabels: [Date] = [] var closingValues: [TradingDayClose] = [] var heading: String = "" init(fundName: String, numYears: Int, closingValues: [TradingDayClose]) { self.heading = fundName + String(" - \(numYears) Year") self.closingValues = closingValues } var body: some View { GroupBox (heading) { let xMin = closingValues.first?.timeStamp let xMax = closingValues.last?.timeStamp let yMin = closingValues.map { $0.close }.min()! let yMax = closingValues.map { $0.close }.max()! let xAxisLabels: [Date] = GetXAxisLabels(xMin: xMin!, xMax: xMax!) var yAxisLabels: [Float] { stride(from: yMin, to: yMax + ((yMax - yMin)/7), by: (yMax - yMin) / 7).map { $0 } } Chart { ForEach(closingValues) { value in LineMark( x: .value("Time", value.timeStamp!), y: .value("Closing Value", value.close) ) .foregroundStyle(Color.blue) .lineStyle(StrokeStyle(lineWidth: 1.25)) } } .chartXScale(domain: xMin!...xMax!) .chartXAxisLabel(position: .bottom, alignment: .center, spacing: 25) { Text("Date") .textFormatting(fontSize: 14) } .chartXAxis { AxisMarks(position: .bottom, values: xAxisLabels) { value in AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) AxisValueLabel(anchor: .top) { if value.as(Date.self) != nil { Text("") } } } } .chartYScale(domain: yMin...yMax) .chartYAxisLabel(position: .leading, alignment: .center, spacing: 25) { Text("Closing Value") .font(Font.custom("Arial", size: 14)) .foregroundColor(.black) } .chartYAxis { AxisMarks(position: .leading, values: yAxisLabels) { value in AxisGridLine(centered: true, stroke: StrokeStyle(lineWidth: 1)) AxisValueLabel() { if let labelValue = value.as(Double.self) { Text(String(format: "$ %.2f", labelValue)) .textFormatting(fontSize: 12) } } } } .chartOverlay { proxy in GeometryReader { geometry in ChartOverlayRectangle(selectedDate: $selectedDate, selectedClose: $selectedClose, proxy: proxy, geometry: geometry, xMin: xMin!, xMax: xMax!, closingValues: closingValues) } } .overlay { XAxisDates(dateLabels: xAxisLabels) } .overlay { DateAndClosingValue(selectedDate: selectedDate ?? Date(), selectedClose: selectedClose ?? 0.0) } } .groupBoxStyle(ChartGroupBoxStyle()) } }
Posted
by ChrisMH.
Last updated
.