Передать свойство прогнозируемого значения наблюдаемого объекта в @Binding

#swift #swiftui #ios14 #xcode12

#swift #swiftui #ios14 #xcode12

Вопрос:

У меня есть главный экран с @FetchRequest , который возвращает FetchResult<Item> . На этом главном экране у меня есть список всех элементов с навигационными ссылками, которые при выборе передают Item в ItemDetail представление. В этом ItemDetail представлении элемент помечен @ObservedObject . Подвидом ItemDetail является ItemPropertiesView , в котором перечислены все свойства элемента. Я передаю свойства элемента непосредственно в @Binding свойства ItemPropertiesView использования $item.{insert property here} . В ItemPropertiesView есть несколько, LineItem где я передаю свойство, используя $ еще раз, в @Binding свойство под названием «значение», которое передается в текстовое поле, которое в конечном итоге может быть изменено.

Моя цель — иметь возможность редактировать это текстовое поле и, как только вы закончите редактирование, иметь возможность сохранить эти изменения в моем основном хранилище данных.

Поскольку это было немного сложно для чтения, вот воссоздание кода:

 struct MainScreen: View {
    @FetchRequest(entity: Item.entity(), sortDescriptors: [NSSortDescriptor(key: "itemName", ascending: true)]) var items: FetchedResults<Item>
    var body: some View {
        NavigationView {
            List {
                ForEach(items, id: .self) { (item: Item) in
                    NavigationLink(destination: ItemDetail(item: item)) {
                        Text(item.itemName ?? "Unknown Item Name")
                    }
                } // ForEach
            }
        }
    } // body
} // MainScreen

struct ItemDetail: View {
    @ObservedObject var item: Item

    var body: some View {
        ItemPropertiesView(itemCost: $item.itemCost)
    }
}

struct ItemPropertiesView: View {
    @Binding var itemCost: String?

    var body: some View {
        LineItem(identifier: "Item Cost", value: $itemCost)
    }
}

struct LineItem: View {
    let identifier: String
    @Binding var value: String

    var body: some View {
        HStack {
            Text(identifier).bold()   Text(": ")
            TextField("Enter value",text: $value)
        }
    }
}
  

Я получаю сообщение об ошибке в ItemDetail: «Компилятор не может выполнить проверку типа этого выражения в разумные сроки; попробуйте разбить выражение на отдельные подвыражения»

Это единственная ошибка, которую я получаю. Я новичок в SwiftUI, поэтому приветствую все отзывы.

Ответ №1:

Просто прочитав код, я предполагаю, что проблема в необязательном свойстве в ItemPropertiesView , просто удалите его

 struct ItemPropertiesView: View {
    @Binding var itemCost: String      // << here !!
    // .. other code
  

и обновить родительский элемент, чтобы у него был переход к необязательному свойству модели CoreData

 struct ItemDetail: View {
    @ObservedObject var item: Item

    var body: some View {
        let binding = Binding(
            get: { self.item.itemCost ?? "" },
            set: { self.item.itemCost = $0 }
        )
        return ItemPropertiesView(itemCost: binding)
    }
}
  

Комментарии:

1. С тех пор я узнал, что можно преобразовать привязку<_?> в привязку<_>?, используя один из других инициалов привязки. Итак, все, что мне нужно было сделать, это если пусть itemCost = Binding($itemCost) { LineItem(…) } в ItemPropertiesView, и это работает, как ожидалось.