Created a Date Selection View in SwiftUI and having an error with No exact matches in call to initializer

33 Views Asked by At

I used a ForEach to present the calender. I am missing something in my code and can't place my finger on it. Any help is needed. This is the error: No exact matches in call to initializer

import SwiftUI import Foundation

struct DateSelectionView: View {
    let calendar = Calendar.current
    let currentDate = Date()

    var daysInMonth: Int {
        calendar.range(of: .day, in: .month, for: Date())!.count
    }

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 20) {
                ForEach(0..<daysInMonth, id: \.self) { day in
                    let date = calendar.date(byAdding: .day, value: day, to: currentDate)!
                    let dayText: String

                    @ViewBuilder
                    func buildDayText() -> some View {
                        if calendar.isDateInToday(date) {
                            Text("Today")
                        } else if calendar.isDateInYesterday(date) {
                            Text("Yesterday")
                        } else if calendar.isDateInTomorrow(date) {
                            Text("Tomorrow")
                        } else {
                            let dateFormatter = DateFormatter()
                            dateFormatter.dateFormat = "dd"
                            Text(dateFormatter.string(from: date))
                        }
                    }

                    buildDayText()
                        .font(.title)
                        .foregroundColor(.blue)
                        .padding(10)
                        .background(Color.gray.opacity(0.2))
                        .cornerRadius(10)
                }
            }
            .padding()
        }
    }
}

struct DateSelectionView_Previews: PreviewProvider {
    static var previews: some View {
        DateSelectionView()
    }
}
2

There are 2 best solutions below

0
Benzy Neez On

Inside your ForEach you have a function declaration, this is why the compiler is getting confused.

You just need to re-organize your code and make the function standalone. Since the function is a ViewBuilder you probably need to move the dateFormatter outside of the function too:

private var dateFormatter: DateFormatter {
    let dateFormatter = DateFormatter()
    dateFormatter.dateFormat = "dd"
    return dateFormatter
}

@ViewBuilder
private func buildDayText(date: Date) -> some View {
    if calendar.isDateInToday(date) {
        Text("Today")
    } else if calendar.isDateInYesterday(date) {
        Text("Yesterday")
    } else if calendar.isDateInTomorrow(date) {
        Text("Tomorrow")
    } else {
        Text(dateFormatter.string(from: date))
    }
}

var body: some View {
    ScrollView(.horizontal, showsIndicators: false) {
        HStack(spacing: 20) {
            ForEach(0..<daysInMonth, id: \.self) { day in
                let date = calendar.date(byAdding: .day, value: day, to: currentDate)!
                // let dayText: String
                buildDayText(date: date)
                    .font(.title)
                    .foregroundColor(.blue)
                    .padding(10)
                    .background(Color.gray.opacity(0.2))
                    .cornerRadius(10)
            }
        }
        .padding()
    }
}
0
EMPIRE On

With @Benzy Neez help the problem has been fixed. Leaving the full completed code in case someone else runs into this issue and is looking for an answer. Thanks @Benzy Neez

import SwiftUI
import Foundation

struct DateSelectionView: View {
    let calendar = Calendar.current
    let currentDate = Date()

    private var dateFormatter: DateFormatter {
        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "dd"
        return dateFormatter
    }

    @ViewBuilder
    private func buildDayText(date: Date) -> some View {
        if calendar.isDateInToday(date) {
            Text("Today")
        } else if calendar.isDateInYesterday(date) {
            Text("Yesterday")
        } else if calendar.isDateInTomorrow(date) {
            Text("Tomorrow")
        } else {
            Text(dateFormatter.string(from: date))
        }
    }

    var daysInMonth: Int {
        calendar.range(of: .day, in: .month, for: Date())!.count
    }

    var body: some View {
        ScrollView(.horizontal, showsIndicators: false) {
            HStack(spacing: 20) {
                ForEach(0..<daysInMonth, id: \.self) { day in
                    let date = calendar.date(byAdding: .day, value: day, to: currentDate)!
                    buildDayText(date: date)
                        .font(.title)
                        .foregroundColor(.blue)
                        .padding(10)
                        .background(Color.gray.opacity(0.2))
                        .cornerRadius(10)
                }
            }
            .padding()
        }
    }
}

struct DateSelectionView_Previews: PreviewProvider {
    static var previews: some View {
        DateSelectionView()
    }
}