我有一个 watchOS 应用程序,有两个屏幕。当我导航到第二个屏幕时,我在控制台中收到以下警告:
ScrollView contentOffset 绑定已读取;这将导致视图性能非常低效,因为只要其 contentOffset 发生变化,ScrollView 的内容就会更新。在绑定创建者和 ScrollView 之间没有父子关系的视图中读取 contentOffset 绑定以避免这种情况。
这似乎与在第二个屏幕中使用 @EnvironmentObject 进行选择器选择有关。如果我删除 @EnvironmentObject 并将其替换为 @State 以进行选择器选择,则不会发生警告。(但是更新不会反映在第一个屏幕上)。
为什么会发生这种情况?我可以做什么来阻止这个警告?
这是我的代码:
第一个屏幕:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var itemManager: ItemManager
var body: some View {
List {
ForEach(itemManager.items.indices) { index in
NavigationLink(destination: ItemView(index: index)) {
VStack(alignment: HorizontalAlignment.leading) {
HStack {
Text(self.itemManager.items[index].name)
Spacer()
Text("x")
Text(String(self.itemManager.items[index].quantity))
}
Text(self.itemManager.items[index].type.rawValue).font(.footnote)
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(ItemManager())
}
}
Run Code Online (Sandbox Code Playgroud)
第二个屏幕:
import SwiftUI
struct ItemView: View {
@EnvironmentObject var itemManager: ItemManager
var index: Int
var body: some View {
VStack {
Text("Update")
Form {
Section {
Picker(selection: $itemManager.items[index].type, label: Text("Food Type")) {
ForEach(FoodType.allCases.sorted()) { type in
Text(type.rawValue).tag(type)
}
}
}
}
}.navigationBarTitle(Text("Item"))
}
}
struct ItemView_Previews: PreviewProvider {
static var previews: some View {
return ItemView(index: 0).environmentObject(ItemManager())
}
}
Run Code Online (Sandbox Code Playgroud)
模型:
import Foundation
enum FoodType: String, CaseIterable, Identifiable, Comparable{
case fruit
case vegetable
case poultry
case bakery
var id: FoodType{self}
static func < (lhs: FoodType, rhs: FoodType) -> Bool {
lhs.rawValue < rhs.rawValue
}
}
struct Item {
var type: FoodType
var quantity: Int
var name: String
}
class ItemManager: ObservableObject {
@Published var items: [Item] =
[
Item(type: FoodType.fruit, quantity: 1, name: "apple"),
Item(type: FoodType.bakery, quantity: 1, name: "french bread"),
Item(type: FoodType.vegetable, quantity: 6, name: "carrots")
]
}
Run Code Online (Sandbox Code Playgroud)
托管控制器:
import WatchKit
import Foundation
import SwiftUI
class HostingController: WKHostingController<AnyView> {
override var body: AnyView {
return AnyView(ContentView()
.environmentObject(ItemManager()))
}
}
Run Code Online (Sandbox Code Playgroud)
我最终在第二个屏幕(ItemView)上使用@State,并在视图消失时设置@EnvironmentObject itemManager。
第一个屏幕:
import SwiftUI
struct ContentView: View {
@EnvironmentObject var itemManager: ItemManager
var body: some View {
List {
ForEach(itemManager.items, id: \.self) { item in
NavigationLink(destination: ItemView(selection: item.type, food: item)) {
VStack(alignment: HorizontalAlignment.leading) {
HStack {
Text(item.name)
Spacer()
Text("x")
Text(String(item.quantity))
}
Text(item.type.rawValue).font(.footnote)
}
}
}
}
}
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
ContentView().environmentObject(ItemManager())
}
}
Run Code Online (Sandbox Code Playgroud)
注意: 我从 Landmark apple 教程中获得了 var itemIndex: Int strategry
第二个屏幕:
import SwiftUI
struct ItemView: View {
@EnvironmentObject var itemManager: ItemManager
@State var selection : FoodType
var food: Item
var itemIndex: Int {
itemManager.items.firstIndex(where: { $0.id == food.id })!
}
var body: some View {
VStack {
Text("Update")
Form {
Section {
Picker(selection: $selection, label: Text("Food Type")) {
ForEach(FoodType.allCases.sorted()) { type in
Text(type.rawValue).tag(type)
}
}
}
}
}.navigationBarTitle(Text("Item"))
.onDisappear {
self.itemManager.items[self.itemIndex].type = self.selection
}
}
}
struct ItemView_Previews: PreviewProvider {
static var previews: some View {
let food = Item(id: UUID(), type: FoodType.fruit, quantity: 1, name: "apple")
return ItemView(selection: FoodType.fruit, food: food)
}
}
Run Code Online (Sandbox Code Playgroud)
| 归档时间: |
|
| 查看次数: |
1975 次 |
| 最近记录: |