首页 > 解决方案 > 将 .environmentObject 与呈现为工作表的视图一起使用会导致 onReceive 不触发/与 @EnvironmentObject 冲突

问题描述

在我的ContentView中,我有一个按钮,可以简单sheet地呈现我的SettingsView. 当视图以模态方式呈现时,我@EnvironmentObject var iconSettings: IconNames的 in似乎存在一些冲突,其中我的函数仅在视图第一次加载时触发,而在使用时永远不会触发。SettingsViewonReceivePicker

环顾四周寻找与此相关的答案,我只能找到与 CoreData 相关的东西,这并没有真正的帮助,但我相信其他人已经经历过这个,所以有一些规范和更通用的东西供其他人参考会很棒。

谢谢!

Button(action: { self.modalDisplayed = true }) {
   Assets.gear
}.sheet(isPresented: $modalDisplayed) {
   SettingsView(state: self.state, loadCards: self.load)
      .environmentObject(IconNames())
}

然后在我的 SettingsView 中,我有以下内容:

struct SettingsView: View {
    @ObservedObject var state: AppState

    @EnvironmentObject var iconSettings: IconNames

    let loadCards: () -> Void

    var body: some View {
        VStack {
            Picker("", selection: $iconSettings.currentIndex) {
                ForEach(Publication.allCases, id: \.pubId) {
                    Text($0.pubName).tag($0.pubId)
                }
            }
            .pickerStyle(SegmentedPickerStyle())
            .padding(20)
            Spacer()
        }
        .onReceive([self.iconSettings.currentIndex].publisher.first()) { value in
            print(value) // only hits on first load, never on tap
            print("")
            let index = self.iconSettings.iconNames.firstIndex(of: UIApplication.shared.alternateIconName) ?? 0
            if index != value { UIApplication.shared.setAlternateIconName(self.iconSettings.iconNames[value]) { error in
                    if let error = error {
                        print(error.localizedDescription)
                    } else {
                        print("Success!")
                    }
                }
            }
        }
    }
}

最后,我的 IconNames 类:

class IconNames: ObservableObject {
    var iconNames: [String?] = [nil]
    @Published var currentIndex = 0

    init() {
        getAlternateIconNames()

        if let currentIcon = UIApplication.shared.alternateIconName {
            self.currentIndex = iconNames.firstIndex(of: currentIcon) ?? 0
        }
    }

    func getAlternateIconNames() {
        if let icons = Bundle.main.object(forInfoDictionaryKey: "CFBundleIcons") as? [String: Any],
            let alternateIcons = icons["CFBundleAlternateIcons"] as? [String: Any]
        {

             for (_, value) in alternateIcons{

                 guard let iconList = value as? Dictionary<String,Any> else{return}
                 guard let iconFiles = iconList["CFBundleIconFiles"] as? [String]
                     else{return}

                 guard let icon = iconFiles.first else{return}
                 iconNames.append(icon)
             }
        }
    }

}

标签: iosswiftswiftui

解决方案


好吧,由于提供的代码快照不能通过复制粘贴来测试,所以只能通过代码阅读,尝试而不是

.onReceive([self.iconSettings.currentIndex].publisher.first()) { value in

用这个

.onReceive(self.iconSettings.$currentIndex) { value in

推荐阅读