Использование .environmentObject с представлением, представленным в виде листа, приводит к тому, что onReceive не срабатывает / конфликтует с @EnvironmentObject - PullRequest
1 голос
/ 10 февраля 2020

В моем ContentView есть кнопка, которая делает простой sheet подарок моего SettingsView. Кажется, есть некоторый конфликт с моим @EnvironmentObject var iconSettings: IconNames в SettingsView, когда представление представлено модально, где моя функция onReceive запускается только при первом просмотре загрузки и никогда, когда Picker используется.

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

Спасибо!

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

Затем в моем окне настроек отображается следующее:

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)
             }
        }
    }

}

1 Ответ

1 голос
/ 10 февраля 2020

Ну, поскольку предоставленный моментальный снимок кода не может быть проверен копированием-вставкой, поэтому только при чтении кода попробуйте вместо

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

использовать этот

.onReceive(self.iconSettings.$currentIndex) { value in
Добро пожаловать на сайт PullRequest, где вы можете задавать вопросы и получать ответы от других членов сообщества.
...