В моем коде у меня есть список, который отображает комментарий объекты:
@Model
final class Comment
{
var text: String
@Relationship(deleteRule: .cascade, inverse: \Document.comment) var document: Document?
@Relationship(deleteRule: .cascade, inverse: \Passage.comment) var passages: [Passage]?
init(text: String)
{
self.text = text
self.passages = []
}
}
И в каждой строке есть кнопка, которая запускает документ , что комментарий связан с:
HStack
{
Text(comment.text)
if let document = comment.document,
let passages = comment.passages
{
Button
{
onPresentCommentInDocument(comment, document, passages)
}
label:
{
Image(systemName: "document")
}
}
else
{
//handle error
}
}
В SwiftData/CloudKit свойства отношений должны быть необязательными, поэтому я развергаю комментарий документ объекта (каждый комментарий объект гарантированно имеет один) и отрывка , чтобы убедиться, что они существуют, и отображение ошибки, если нет. Я храню их в @state переменных, затем передаю их в структуру с именем DocumentControllerView :
struct DocumentControllerView: View
{
@Binding var commentToEdit: Comment?
@Binding var commentPassagesToEdit: [Passage]?
@Binding var commentDocumentToPresent: Document?
@State private var interiorDocumentToPresent: Document?
private var documentToPresent: Binding
{
Binding(get:
{
if self.commentToEdit != nil && self.commentPassagesToEdit != nil,
let commentDocumentToPresent = self.commentDocumentToPresent
{
commentDocumentToPresent
}
else
{
self.interiorDocumentToPresent
}
},
set:
{
newValue in
if (newValue == nil)
{
self.commentDocumentToPresent = nil
self.commentToEdit = nil
self.commentPassagesToEdit = nil
self.interiorDocumentToPresent = nil
}
})
}
...
< /code>
DocumentViewController запустит документ , который либо внутренний для него (созданный через свой собственный пользовательский интерфейс), либо передается из комментария (как упомянуто). Если из комментария , он запустит .fullScreenCover , который позволит пользователю добавить отрывок к комментарию :
.fullScreenCover(item: self.documentToPresent)
{
_ in
if let commentPassagesToEditBinding = Binding(self.$commentPassagesToEdit)
{
Button("Add Passage")
{
commentPassagesToEditBinding.wrappedValue.append(Passage())
self.commentToEdit?.passages?.append(Passage())
}
Text("commentPassagesToEditBinding.wrappedValue.count: \(commentPassagesToEditBinding.wrappedValue.count)")
Text("self.commentToEdit?.passages?.count: \(String(describing: self.commentToEdit?.passages?.count))")
}
}
< /code>
As you can see, I need to append to both the unwrapped binding so self.commentPassagesToEdit останется текущим, чтобы я мог ссылаться на это, а также на источник истины, чтобы обновить модель. Необходимость сделать это с обеими вещами кажется странным.
Когда я пытаюсь передавать три вышеупомянутых свойства в виде VAR, а не привязки, обновление и ссылка из источника истины работает нормально, однако я не могу установить их на ноль, когда документ отклоняется, поэтому они должны быть привязки. быть необязательным. Я также не хочу просто игнорировать развертывание опционов и сначала, чтобы я мог отобразить ошибку, если это необходимо. < /P>
Есть ли лучший способ сделать это?@Model
final class Comment
{
var text: String
@Relationship(deleteRule: .cascade, inverse: \Document.comment) var document: Document?
@Relationship(deleteRule: .cascade, inverse: \Passage.comment) var passages: [Passage]?
init(text: String)
{
self.text = text
self.passages = []
}
}
@Model
final class Document
{
var comment: Comment?
init()
{
}
}
@Model
final class Passage
{
var comment: Comment?
init()
{
}
}
struct ContentView: View
{
@Environment(\.modelContext) private var modelContext
@State private var commentToEdit: Comment?
@State private var commentPassagesToEdit: [Passage]?
@State private var commentDocumentToPresent: Document?
var body: some View
{
CommentList(onPresentCommentInDocument:
{
comment, document, passages in
self.commentToEdit = comment
self.commentPassagesToEdit = passages
self.commentDocumentToPresent = document
})
.toolbar
{
ToolbarItem(placement: .navigationBarLeading)
{
DocumentControllerView(commentToEdit: self.$commentToEdit,
commentPassagesToEdit: self.$commentPassagesToEdit,
commentDocumentToPresent: self.$commentDocumentToPresent)
}
}
.task
{
do
{
try modelContext.delete(model: Comment.self)
let comment = Comment(text: "Comment 1")
comment.document = Document()
comment.passages?.append(Passage())
self.modelContext.insert(comment)
}
catch
{
fatalError(error.localizedDescription)
}
}
}
}
struct CommentList: View
{
var onPresentCommentInDocument: ((Comment, Document, [Passage]) -> Void)
@Query private var comments: [Comment]
var body: some View
{
List
{
ForEach(self.comments)
{
comment in
HStack
{
Text(comment.text)
if let document = comment.document,
let passages = comment.passages
{
Button
{
onPresentCommentInDocument(comment, document, passages)
}
label:
{
Image(systemName: "document")
}
}
else
{
//handle error
}
}
}
}
}
}
struct DocumentControllerView: View
{
@Binding var commentToEdit: Comment?
@Binding var commentPassagesToEdit: [Passage]?
@Binding var commentDocumentToPresent: Document?
@State private var interiorDocumentToPresent: Document?
private var documentToPresent: Binding
{
Binding(get:
{
if self.commentToEdit != nil && self.commentPassagesToEdit != nil,
let commentDocumentToPresent = self.commentDocumentToPresent
{
commentDocumentToPresent
}
else
{
self.interiorDocumentToPresent
}
},
set:
{
newValue in
if (newValue == nil)
{
self.commentDocumentToPresent = nil
self.commentToEdit = nil
self.commentPassagesToEdit = nil
self.interiorDocumentToPresent = nil
}
})
}
var body: some View
{
Text("Document Controller")
.fullScreenCover(item: self.documentToPresent)
{
_ in
if let commentPassagesToEditBinding = Binding(self.$commentPassagesToEdit)
{
Button("Add Passage")
{
commentPassagesToEditBinding.wrappedValue.append(Passage())
self.commentToEdit?.passages?.append(Passage())
}
Text("commentPassagesToEditBinding.wrappedValue.count: \(commentPassagesToEditBinding.wrappedValue.count)")
Text("self.commentToEdit?.passages?.count: \(String(describing: self.commentToEdit?.passages?.count))")
}
}
}
}
Подробнее здесь: https://stackoverflow.com/questions/797 ... it-without