UPGRADE YOUR SKILLS: Learn advanced Swift and SwiftUI on Hacking with Swift+! >>

Getting an error when using interpolated strings with .accessibilityLabel

Forums > 100 Days of SwiftUI

I was working through Project 15 and when I was doing the challenges of adding accessibility to old projects I kept getting an error if I passed anything other than a string literal to accessibilityLabel. The error is "The compiler is unable to type-check this expression in reasonable time; try breaking up the expression into distinct sub-expressions."

So if I had: .accessibilityLabel("Business")

It worked fine. But if I had: .accessibilityLabel("\(item.name)")

I'd get an error.

This is from iExpense and item is an ExpenseItem and the name property is a string.

2      

Here's ContentView:

struct ContentView: View {
    @StateObject var expenses = Expenses()
    @State private var showingAddExpense = false

    var body: some View {
        NavigationView {
            List {
                Section {
                    ForEach(expenses.items) { item in
                        if item.type == "Business"{
                            HStack {
                                VStack(alignment: .leading) {
                                    Text(item.name)
                                        .font(.headline)
                                    Text(item.type)
                                }

                                Spacer()
                                amountView(amount: item.amount)
                            }
                            .accessibilityLabel("\(item.name)") //error occurs here
                            .accessibilityHint("Business")
                        }
                    }
                    .onDelete(perform: removeItems)
                }

                Section {
                    ForEach(expenses.items) { item in
                        if item.type == "Personal" {
                            HStack {
                                VStack(alignment: .leading) {
                                    Text(item.name)
                                        .font(.headline)
                                    Text(item.type)
                                }

                                Spacer()
                                amountView(amount: item.amount)
                            }
                            .accessibilityLabel("\(item.name)")
                            .accessibilityHint("Personal")
                        }
                    }
                    .onDelete(perform: removeItems)
                }
            }
            .navigationTitle("iExpense")
            .toolbar {
                Button {
                    showingAddExpense = true
                } label: {
                    Image(systemName: "plus")
                }
            }
        }
        .sheet(isPresented: $showingAddExpense) {
            AddView(expenses: expenses)
        }
    }

    func removeItems(at offsets: IndexSet) {
        expenses.items.remove(atOffsets: offsets)
    }
}

struct amountView: View {
    let amount: Double
    private let currency = FloatingPointFormatStyle<Double>.Currency(code: Locale.current.currencyCode ?? "USD")

    var body: some View {
        if amount < 10.0 {
            Text(amount, format: currency)
                .foregroundColor(.green)
        } else if amount < 100.0 {
            Text(amount, format: currency)
                .foregroundColor(.yellow)
        } else {
            Text(amount, format: currency)
                .foregroundColor(.red)
        }
    }
}

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView()
    }
}

Here's the ExpenseItem struct:

 struct ExpenseItem: Identifiable, Codable {
    var id = UUID()
    let name: String
    let type: String
    let amount: Double
}

2      

I also tried cleaning the build folder, closing/reopening the project, closing/reopening xcode and rebooting.

2      

Try to refactor the Sections out into another view

EG

struct SectionView: View {
    let expenses: Expenses
    let type: String

    var body: some View {
        ForEach(expenses.items) { item in
            if item.type == type {
                HStack {
                    VStack(alignment: .leading) {
                        Text(item.name)
                            .font(.headline)
                        Text(item.type)
                    }

                    Spacer()
                    AmountView(amount: item.amount)
                }
                .accessibilityLabel("\(item.name)")
                .accessibilityHint("\(type)")
            }
        }
        .onDelete(perform: removeItems)
    }

    func removeItems(at offsets: IndexSet) {
        expenses.items.remove(atOffsets: offsets)
    }
}

then in ContentView

struct ContentView: View {
    @StateObject var expenses = Expenses()
    @State private var showingAddExpense = false

    var body: some View {
        NavigationView {
            List {
                Section {
                    SectionView(expenses: expenses, type: "Business")
                }

                Section {
                    SectionView(expenses: expenses, type: "Personal")
                }
            }
            .navigationTitle("iExpense")
            .toolbar {
                Button {
                    showingAddExpense = true
                } label: {
                    Image(systemName: "plus")
                }
            }
        }
        .sheet(isPresented: $showingAddExpense) {
            AddView(expenses: expenses)
        }
    }
}

2      

Since item.name is already a String, did you try just using .accessibilityLabel(item.name) without the string interpolation?

And a separate note: You should really filter your expenses before you loop through them rather than having an if clause in the ForEach.

2      

@roosterboy Re: filtering, I remember I tried that but there was a problem that made it difficult to implement. I asked here about it and the best solution anyone had was using the if statements. I can't say it's elegant, I was inclined to try something like we have in C#/.NET, items.where(x => x.type == "Business"), but I couldn't find a syntactical equivalent.

2      

Hacking with Swift is sponsored by Essential Developer

SPONSORED Join a FREE crash course for mid/senior iOS devs who want to achieve an expert level of technical and practical skills – it’s the fast track to being a complete senior developer! Hurry up because it'll be available only until April 28th.

Click to save your free spot now

Sponsor Hacking with Swift and reach the world's largest Swift community!

Archived topic

This topic has been closed due to inactivity, so you can't reply. Please create a new topic if you need to.

All interactions here are governed by our code of conduct.

 
Unknown user

You are not logged in

Log in or create account
 

Link copied to your pasteboard.