【问题标题】:Navigation Bar Items with @EnvironmentObject带有@EnvironmentObject 的导航栏项目
【发布时间】:2020-02-17 15:21:26
【问题描述】:

我想使用 SwiftUI 创建一个Settings 视图。我主要是拿苹果官方关于SwiftUI的例子来实现我的代码。设置视图应该可以切换是否显示我最喜欢的项目。

现在我有一个地标列表和一个设置视图。

struct Landmark: Hashable, Codable, Identifiable {
    var id: Int
    var imageName: String
    var title: String
    var isFavorite: Bool
    var description: String

    enum CodingKeys: String, CodingKey {
        case id, imageName, title, description
    }
}
final class UserData: ObservableObject {
    @Published var showFavoriteOnly: Bool = false
    @Published var items: [Landmark] = landmarkData
    @Published var showProfile: Bool = false
}
struct ItemList: View {
    @EnvironmentObject var userData: UserData
    @State var trailing: Bool = false

    init() {
        UITableView.appearance().separatorStyle = .none
    }

    var body: some View {
        NavigationView {
            List {
                VStack {
                    CircleBadgeView(text: String(landmarkData.count), thickness: 2)
                    Text("Tutorials available")
                }.frame(minWidth:0, maxWidth: .infinity)

                ForEach(userData.items) { landmark in
                    if !self.userData.showFavoriteOnly || landmark.isFavorite {
                        ZStack {
                            Image(landmark.imageName)
                                .resizable()
                                .frame(minWidth: 0, maxWidth: .infinity)
                                .cornerRadius(10)
                                .overlay(ImageOverlay(text: landmark.title), alignment: .bottomTrailing)
                            Text(String(landmark.isFavorite))


                            NavigationLink(destination: TutorialDetailView(landmark: landmark)) {
                                EmptyView()
                            }.buttonStyle(PlainButtonStyle())
                        }
                    }
                }
            }.navigationBarTitle("Tutorials")
                .navigationBarItems(trailing: trailingItem())
        }
    }
}

extension ItemList {
    func trailingItem () -> some View {
        return HStack {

            if userData.showProfile {
                NavigationLink(destination: ProfileView()) {
                    Image(systemName: "person.circle")
                        .imageScale(.large)
                        .accessibility(label: Text("Profile"))
                }
            }

            NavigationLink(destination: SettingsView().environmentObject(userData)) {
                Image(systemName: "gear")
                    .imageScale(.large)
                    .accessibility(label: Text("Settings"))
            }
        }
    }
}

如您所见,我的 SettingsView 可以从我的 NavigationView 的 navigationBarItems 访问。我不知道这是否是问题所在,但是当我将 Toggle 放入 ListView 时,它按预期工作。但是现在当我触发切换以启用只收藏我的应用程序时立即崩溃。

我尝试从SettingsView 触发Show profile 切换并且它有效。

struct SettingsView: View {
    @EnvironmentObject var userData: UserData

    var body: some View {
        Form {
            Section(header: Text("General")) {
                Toggle(isOn: $userData.showProfile) {
                    Text("Show profile")
                }
                Toggle(isOn: $userData.showFavoriteOnly) {
                    Text("Favorites only")
                }
            }

            Section(header: Text("UI")) {
                Toggle(isOn: .constant(false)) {
                    Text("Dark mode")
                }

                NavigationLink(destination: Text("third")) {
                    Text("Third navigation")
                }
            }

        }.navigationBarTitle(Text("Settings"), displayMode: .inline)
    }
}

简而言之,当我触发Show only favorite 切换时,崩溃出现在我的SettingsView 中,然后我尝试返回上一个视图ItemListView

我能得到的关于错误的唯一信息是Thread 1: EXC_BAD_INSTRUCTION (code=EXC_I386_INVOP, subcode=0x0)

你可以在我的 GitHub 上找到整个项目:https://github.com/Hurobaki/swiftui-tutorial

非常感谢您的帮助:)

【问题讨论】:

  • 根据经验,NavigationLink 只能在NavigationView 正文中使用,因此以不同的方式呈现您的Settings 视图。
  • 那么如何从navigationBarItems导航?
  • 什么是崩溃错误信息?你能提供我们可以复制并粘贴到 Xcode 中重现的示例代码吗?因为这段代码不是一个独立的工作示例。
  • @KevinRenskers 我已经编辑了我的问题,并给了你我的 Github,以便更容易获得该项目。希望你没事

标签: ios swift swiftui


【解决方案1】:

这是您的示例代码的最小版本,它可以工作:

struct Landmark: Hashable, Codable, Identifiable {
  var id: Int
  var imageName: String
  var title: String
  var isFavorite: Bool
  var description: String
}

final class UserData: ObservableObject {
  @Published var showFavoriteOnly: Bool = false
  @Published var items: [Landmark] = [
    Landmark(id: 1, imageName: "a", title: "a", isFavorite: true, description: "A"),
    Landmark(id: 2, imageName: "b", title: "b", isFavorite: false, description: "B")
  ]
}

struct ContentView: View {
  @EnvironmentObject var userData: UserData

  var body: some View {
    NavigationView {
      List(userData.items.filter { !userData.showFavoriteOnly || $0.isFavorite }) { landmark in
        Text(String(landmark.isFavorite))
      }
      .navigationBarTitle("Tutorials")
      .navigationBarItems(trailing: trailingItem())
    }
  }

  func trailingItem () -> some View {
    return HStack {
      NavigationLink(destination: SettingsView()) {
        Text("Settings")
      }
    }
  }
}

struct SettingsView: View {
  @EnvironmentObject var userData: UserData

  var body: some View {
    Form {
      Section(header: Text("General")) {
        Toggle(isOn: $userData.showFavoriteOnly) {
          Text("Favorites only")
        }
      }
    }.navigationBarTitle(Text("Settings"), displayMode: .inline)
  }
}

【讨论】:

  • 你能解释一下我的错误在哪里吗?谢谢你的例子,我当然会试试:)
  • 并非如此,因为我无法按原样运行您的代码。所以我删除了所有我不需要让它工作的位,它运行良好。
  • 至少不需要将.environmentObject(userData) 传递给SettingsView,我在列表中使用.filter .. 但我不知道是什么导致了你的崩溃代码。您指向 TutorialDetailView 的空 NavigationLink 也很奇怪。
  • 我已对我的 OP 进行了编辑,因此您可以完全访问我的代码 :) 我会尝试您的解决方案
  • 我已经测试了你的 GitHub 项目,这对我来说也不会崩溃?‍♂️
猜你喜欢
  • 1970-01-01
  • 1970-01-01
  • 1970-01-01
  • 2013-11-13
  • 2023-03-30
  • 1970-01-01
  • 2014-12-19
  • 2018-01-27
  • 1970-01-01
相关资源
最近更新 更多