admaDIC App Development & IT Solutions

SwiftUI Pie Charts

by Annett Schwarze | 2025-05-30

SwiftUI Charts support creating pie charts since iOS 17. To create a pie chart, use a `Chart` view and place `SectorMark`s inside.

With the parameter `innerRadius` a ring chart can be created. Data labels can be inserted with the `.annotation` modifier.

        


        import SwiftUI
import Charts

struct SamplePieChartView: View {
    struct Record: Identifiable {
        let id: UUID = UUID()
        var name: String
        var value: Double
    }

    @State private var earnings: [Record] = []
    private let demoEarnings: [Record] = [
        Record(name: "Tax Return", value: 50),
        Record(name: "Interest", value: 70),
        Record(name: "Payment", value: 1000)
    ]
    @State private var expenses: [Record] = []
    private let demoExpenses: [Record] = [
        Record(name: "Groceries", value: 80),
        Record(name: "Insurance", value: 100),
        Record(name: "Bicycle repair", value: 20)
    ]

    var body: some View {
        Text("SwiftUI Pie Chart")
            .font(.largeTitle)

        VStack(spacing: 16) {
            VStack {
                let total = earnings.reduce(0) { $0 + $1.value }
                HStack {
                    Text("Earnings")
                    Text(total, format: .currency(code: Locale.current.currency?.identifier ?? "$"))
                }
                .font(.title2)
                if #available(iOS 17.0, *) {
                    Chart(earnings) { record in
                        SectorMark(angle: .value(
                            Text(verbatim: record.name),
                            record.value / total))
                        .foregroundStyle(by: .value(
                            Text(verbatim: record.name),
                            record.name
                        ))
                    }
                } else {
                    Text("iOS 17.0 required")
                        .foregroundStyle(.secondary)
                }
            }
            .padding(12)
            .background {
                Color.white
            }
            .clipShape(RoundedRectangle(cornerRadius: 16))
            VStack {
                let total = expenses.reduce(0) { $0 + $1.value }
                HStack {
                    Text("Expenses")
                    Text(total, format: .currency(code: Locale.current.currency?.identifier ?? "$"))
                }
                .font(.title2)
                if #available(iOS 17.0, *) {
                    Chart(expenses) { record in
                        SectorMark(angle: .value(
                            Text(verbatim: record.name),
                            record.value / total), innerRadius: .ratio(0.5), angularInset: 4)
                        .annotation(position: .overlay, alignment: .center) {
                            VStack(spacing: 0) {
                                Text("\(record.name)")
                                Text(record.value, format: .currency(code: Locale.current.currency?.identifier ?? "$"))
                            }
                            .padding(4)
                            .clipShape(RoundedRectangle(cornerRadius: 8))
                            .background {
                                Color.white
                                    .clipShape(RoundedRectangle(cornerRadius: 8))
                                    .shadow(radius: 4)
                            }
                        }
                        .foregroundStyle(by: .value(
                            Text(verbatim: record.name),
                            record.name
                        ))
                    }
                } else {
                    Text("iOS 17.0 required")
                        .foregroundStyle(.secondary)
                }
            }
            .padding(12)
            .background {
                Color.white
            }
            .clipShape(RoundedRectangle(cornerRadius: 16))
        }
        .padding()
        .onTapGesture {
            loadData()
        }
        .background {
            Color(white: 0.9)
        }
        .onTapGesture { // for testing
            loadData()
        }
        .onAppear {
            loadData()
        }
    }

    private func loadData() {
        earnings = []
        expenses = []
        Task {
            for earning in demoEarnings {
                try? await Task.sleep(for: .milliseconds(800))
                withAnimation(.spring(duration: 0.8, bounce: 0.3)) {
                    earnings.append(earning)
                }
            }
            for expense in demoExpenses {
                try? await Task.sleep(for: .milliseconds(800))
                withAnimation(.spring(duration: 0.8, bounce: 0.3)) {
                    expenses.append(expense)
                }
            }
        }
    }
}

#Preview {
    SamplePieChartView()
}
SwiftUI Pie Chart

 

www.admadic.de | webmaster@admadic.de | Legal Notice and Trademarks | Privacy
© 2005-2007 - admaDIC | All Rights Reserved
All other trademarks and/or registered trademarks are the property of their respective owners
Last Change: Fri May 30 09:30:32 2025 GMT