我在
Type '()' cannot conform to 'View'"
线上收到 if let birthday = contact.birthday, let birthdayDate = Calendar.current.date(from: birthday) {
错误。查看错误日志后,我发现:Only concrete types such as structs, enums and classes can conform to protocols
和Required by static method 'buildBlock' where 'C0' = '()'
。
这是我的生日行文件,我遇到了
"Type '()' cannot conform to 'View'"
错误
//
// BirthdayRow.swift
// B-Day
//
// Created by Joshua Wolfson on 29/7/2023.
//
import SwiftUI
struct GaugeProgressStyle: ProgressViewStyle {
var strokeColor = Color.primary
var strokeWidth = 7.0
func makeBody(configuration: Configuration) -> some View {
let fractionCompleted = configuration.fractionCompleted ?? 0
return ZStack {
Circle()
.stroke(.tertiary, style: StrokeStyle(lineWidth: strokeWidth, lineCap: .round))
Circle()
.trim(from: 0, to: fractionCompleted)
.stroke(strokeColor, style: StrokeStyle(lineWidth: strokeWidth, lineCap: .round))
.rotationEffect(.degrees(-90))
}
}
}
struct BirthdayRow: View {
@State private var progress: Double
let contact: Contact
init(contact: Contact) {
self.contact = contact
self.progress = Self.calculateProgress(contact: contact)
}
static func calculateProgress(contact: Contact) -> Double {
guard let birthday = contact.birthday, let birthdayDate = Calendar.current.date(from: birthday) else {
return 0.0
}
let currentDate = Date()
let calendar = Calendar.current
let daysInYear: Double = 365.0
let daysRemaining = Double(calendar.dateComponents([.day], from: currentDate, to: birthdayDate).day ?? 0)
return (daysInYear - daysRemaining) / daysInYear * 100.0
}
var body: some View {
VStack {
HStack {
VStack(alignment: .leading) {
Text("\(contact.firstName) \(contact.lastName)")
.font(.title3)
.fontWeight(.bold)
HStack {
Text(contact.category)
.foregroundColor(Color.gray)
Text("•")
.fontWeight(.black)
if let birthday = contact.birthday, let birthdayDate = Calendar.current.date(from: birthday)
{ //I'm receiving "Type '()' cannot conform to 'View'" error here
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
Text(dateFormatter.string(from: birthdayDate))
.foregroundColor(Color.gray)
} else {
Text("Unknown")
.foregroundColor(Color.red)
}
}
}
Spacer()
ProgressView(value: progress, total: 100.0)
.progressViewStyle(GaugeProgressStyle())
.frame(width: 26, height: 26)
.contentShape(Rectangle())
}
.padding(.horizontal)
}
}
}
struct BirthdayRow_Previews: PreviewProvider {
static var contacts = ModelData().contacts
static var previews: some View {
Group {
BirthdayRow(contact: contacts[0])
BirthdayRow(contact: contacts[1])
}
.previewLayout(.fixed(width: 300, height: 70))
}
}
这是我的 ModelData 文件,有帮助吗?
//
// ModelData.swift
// B-Day
//
// Created by Joshua Wolfson on 5/8/2023.
//
import Foundation
import Contacts
import SwiftUI
final class ModelData: ObservableObject {
@Published var contacts: [Contact] = []
init() {
Task {
let fetchedContacts = await fetchAllContacts()
DispatchQueue.main.async {
self.contacts = fetchedContacts
}
}
}
}
struct Contact: Identifiable {
let id = UUID()
let category: String // This will contain the group name
let firstName: String
let lastName: String
let birthday: DateComponents?
}
func fetchAllContacts() async -> [Contact] {
var contacts = [Contact]()
let store = CNContactStore()
// Request the contact's identifier and group information
let keys = [CNContactGivenNameKey, CNContactFamilyNameKey, CNContactBirthdayKey, CNContactIdentifierKey, CNGroupNameKey, CNGroupIdentifierKey] as [CNKeyDescriptor]
let fetchRequest = CNContactFetchRequest(keysToFetch: keys)
fetchRequest.unifyResults = true // To fetch contacts from all accounts and groups
do {
try store.enumerateContacts(with: fetchRequest) { contact, _ in
// Fetch the group name using the identifier
if let groupName = try? store.groups(matching: nil).first(where: { group in
return group.identifier == contact.identifier
})?.name {
contacts.append(Contact(category: groupName, firstName: contact.givenName, lastName: contact.familyName, birthday: contact.birthday))
} else {
contacts.append(Contact(category: "Ungrouped", firstName: contact.givenName, lastName: contact.familyName, birthday: contact.birthday))
}
}
} catch {
print("Error: \(error.localizedDescription)")
}
return contacts
}
我的内容视图如下:
//
// ContentView.swift
// B-Day
//
// Created by Joshua Wolfson on 28/7/2023.
//
import Contacts
import SwiftUI
struct ContentView: View {
@State private var selection = "All"
@EnvironmentObject var modelData: ModelData
var filteredContacts: [Contact] {
modelData.contacts.filter { contact in
(selection == "All" || contact.category == selection)
}
}
var availableCategories: [String] {
var categories = ["All"]
categories.append(contentsOf: Set(modelData.contacts.map { $0.category }).sorted())
return categories
}
var body: some View {
NavigationStack{
List {
ForEach(filteredContacts) {contact in
NavigationLink {
BirthdayDetail(contact: contact)
} label: {
BirthdayRow(contact: contact)
}
}
}
.navigationTitle(selection == "All" ? "Birthdays" : selection)
.toolbar {
ToolbarItem (placement: .navigationBarLeading){
Menu(content: {
Picker("Destination", selection: $selection) {
ForEach(availableCategories, id: \.self) {
Text($0)
}
}
},
label: { Label ("Filter", systemImage: "line.horizontal.3.decrease.circle") })
}
ToolbarItem (placement: .navigationBarTrailing) {
Button {
print("Sync Contacts")
} label: {
Image (systemName: "arrow.triangle.2.circlepath")
}
}
ToolbarItem (placement: .navigationBarTrailing) {
Button {
print("Add Birthday")
} label: {
Image(systemName: "plus")
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView()
}
}
这是我的主要内容:
// B_DayApp.swift
// B-Day
//
// Created by Joshua Wolfson on 28/7/2023.
//
import SwiftUI
import Contacts
@main
struct B_DayApp: App {
@StateObject private var modelData = ModelData()
var body: some Scene {
WindowGroup {
ContentView()
.environmentObject(modelData)
.onAppear {
Task.init {
await fetchAllContacts()
}
}
}
}
}
p.s 抱歉代码超载,这是我的第一篇文章。
您不能将以下代码放入 if 语句中。
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = "dd/MM/yyyy"
上面的代码无法执行,因为它在
var body: some View
里面。
因此,您应该避免在
var body: some View
内处理上述代码。