上述错误发生在我正在创建的选择器处。我正在尝试从 @Bindable 类属性设置默认值。
在 Xcode 中扩展错误并没有真正帮助我
Requirement from conditional conformance of 'Section<TableHeaderRowContent<V, Text>, Content, EmptyTableRowContent<V>>' to 'View' (SwiftUI.Section)
所以我的选取器在完整视图的上下文中定义如下。请注意,父视图的调用站点很简单 - EditGreetingCardView(greetingCard: Bindable(greetingCard!))。
struct EditGreetingCardView: View {
@Environment(\.modelContext) var modelContext
@Query(sort: [
SortDescriptor(\EventType.eventName)
]) var events: [EventType]
@Bindable private var greetingCard: GreetingCard
init(greetingCard: Bindable<GreetingCard>) {
let navBarAppearance = UINavigationBarAppearance()
navBarAppearance.largeTitleTextAttributes = [
.foregroundColor: UIColor.systemGreen,
.font: UIFont(name: "ArialRoundedMTBold", size: 35)!]
navBarAppearance.titleTextAttributes = [
.foregroundColor: UIColor.systemGreen,
.font: UIFont(name: "ArialRoundedMTBold", size: 20)!]
UINavigationBar.appearance().standardAppearance = navBarAppearance
UINavigationBar.appearance().scrollEdgeAppearance = navBarAppearance
UINavigationBar.appearance().compactAppearance = navBarAppearance
_greetingCard = greetingCard
}
var body: some View {
NavigationView {
Form {
Section("Details") {
Picker("Select type", selection: $greetingCard.eventType) {
Text("Unknown Event")
.tag(Optional<EventType>.none) //basically added empty tag and it solve the case
if events.isEmpty == false {
Divider()
ForEach(events) { event in
Text(event.eventName)
.tag(Optional(event))
}
}
}
.navigationTitle(greetingCard.cardName ?? "Card Not Named")
}
}
}
错误出现在选取器线上。我的 Bindable 定义为
@Bindable private var greetingCard: GreetingCard
班级是:
import Foundation
import SwiftData
import UIKit
/// This is used to build a gallery of Greeting Cards
@Model
final class GreetingCard: CustomDebugStringConvertible {
var cardName: String?
@Attribute(.externalStorage) var cardFront: Data?
var eventType: EventType?
var cardManufacturer: String?
var cardURL: URL?
@Relationship(deleteRule: .cascade, inverse: \Card.cardFront) var cards: [Card]? = []
init(cardName: String?, cardFront: Data?, eventType: EventType? = nil, cardManufacturer: String? = nil, cardURL: URL?) {
self.cardName = cardName
self.cardFront = cardFront ?? UIImage(named: "frontImage")!.pngData()!
self.eventType = eventType
self.cardManufacturer = cardManufacturer
self.cardURL = cardURL
}
/// A helper value that exposes the card as an Image either a blank image or the value of the image from the realted GreetingCard
func cardUIImage() -> UIImage {
let defaultImage: UIImage = UIImage(data: (cardFront)!) ?? UIImage(named: "frontImage")!
return defaultImage
}
}
好吧,问题不是视图本身,而是由 SwiftData、CoreDataOptions 和 TextField 中的 Binding 引起的许多不同问题。以下博客文章确实帮助我理解和解决了我的代码:CoreData 和 Bindings
因此我重组了 SwiftData 类,为所有属性设置默认值,从而删除了可选值。现在,视图可以使用以下代码正常工作:
struct EditGreetingCardView: View {
@Environment(\.modelContext) var modelContext
@Bindable private var greetingCard: GreetingCard
@State var frontImageSelected: Image? = Image("frontImage")
@State var shouldPresentCamera = false
@State var frontPhoto = false
@State var captureFrontImage = false
@Query(sort: [
SortDescriptor(\EventType.eventName)
]) var events: [EventType]
init(greetingCard: Bindable<GreetingCard>) {
_greetingCard = greetingCard
}
var body: some View {
Form {
// VStack {
Section {
Picker("Select type", selection: $greetingCard.eventType) {
Text("Unknown Event")
.tag(Optional<EventType>.none) //basically added empty tag and it solve the case
if events.isEmpty == false {
Divider()
ForEach(events) { event in
Text(event.eventName)
.tag(Optional(event))
}
}
}
}
Section("Details") {
TextField("Description", text: $greetingCard.cardName)
TextField("Manufacturer", text: $greetingCard.cardManufacturer)
TextField("Website", text: $greetingCard.cardURL)
}
Section("Card Image") {
ZStack {
Image(uiImage: greetingCard.cardUIImage())
.resizable()
.aspectRatio(contentMode: .fit)
.shadow(radius: 10 )
Image(systemName: "camera.fill")
.foregroundColor(.white)
.font(.largeTitle)
.shadow(radius: 10)
.frame(width: 200)
.onTapGesture { self.frontPhoto = true }
.actionSheet(isPresented: $frontPhoto) { () -> ActionSheet in
ActionSheet(
title: Text("Choose mode"),
message: Text("Select one."),
buttons: [ActionSheet.Button.default(Text("Camera"), action: {
self.captureFrontImage.toggle()
self.shouldPresentCamera = true
}),
ActionSheet.Button.default(Text("Photo Library"), action: {
self.captureFrontImage.toggle()
self.shouldPresentCamera = false
}),
ActionSheet.Button.cancel()])
}
.sheet(isPresented: $captureFrontImage) {
ImagePicker(
sourceType: self.shouldPresentCamera ? .camera : .photoLibrary,
image: $frontImageSelected,
isPresented: self.$captureFrontImage)
}
}
.frame(width: 230, height: 230)
}
}
.navigationTitle(greetingCard.cardName)
}
}