【发布时间】:2020-05-21 18:27:46
【问题描述】:
[编辑(1) 以反映posting of streamlined app 以说明问题:]。
[编辑(2):完全删除 EnvironmentObject 和应用程序现在可以工作了!不理解为什么会刷新正文,因为没有修改 @State 变量...文本末尾的代码]
我正在编写一个应用程序,它在某些时候会根据一组规则显示一些与 2 个数组的内容相关的文本。这些规则可以在设置视图中设置,作为用户的偏好。
因此,当用户更改他希望在“设置”中应用的规则时,需要重新评估该文本。
但当然,事情并不那么容易。
我在主 ContentView 上将设置视图显示为模态,当我关闭该模态时,不会重绘 ContentView 的主体...
我使用 @Published 变量创建了一个 EnvironmentObject,以跟踪所有用户偏好(也写入 UserDefaults),并与我的 ContentView 和 SettingsView 共享该 @EnvironmentObject,希望成为一个被观察的对象,它的更改会触发我的 ContentView 的刷新。
不是这样……
有什么想法可以帮助我继续前进吗?任何指针将不胜感激(再次!)。
Posted app on GitHub 具有以下架构:
一个appState环境对象,ContentView 显示一组文本,具体取决于在
一个settingsView
UserDefaults 在AppDelegate 中初始化。
感谢您对此的任何帮助...
内容视图:
import SwiftUI
struct ContentView: View {
@State var modalIsPresented = false // The "settingsView" modally presented as a sheet
@State private var modalViewCaller = 0 // This triggers the appropriate modal (only one in this example)
var body: some View {
NavigationView {
VStack {
Spacer()
VStack {
Text(generateStrings().text1)
.foregroundColor(Color(UIColor.systemGreen))
Text(generateStrings().text2)
} // end of VStack
.frame(maxWidth: .infinity, alignment: .center)
.lineLimit(nil) // allows unlimited lines
.padding(.all)
Spacer()
} // END of main VStack
.onAppear() {
self.modalViewCaller = 0
}
.navigationBarTitle("Test app", displayMode: .inline)
.navigationBarItems(leading: (
Button(action: {
self.modalViewCaller = 6 // SettingsView
self.modalIsPresented = true
}
) {
Image(systemName: "gear")
.imageScale(.large)
}
))
} // END of NavigationView
.sheet(isPresented: $modalIsPresented, content: sheetContent)
.navigationViewStyle(StackNavigationViewStyle()) // This avoids dual column on iPad
} // END of var body: some View
// MARK: @ViewBuilder func sheetContent() :
@ViewBuilder func sheetContent() -> some View {
if modalViewCaller == 6 {
SettingsView()
}
} // END of func sheetContent
// MARK: generateStrings() : -
func generateStrings() -> (text1: String, text2: String, recapText: String, isHappy: Bool) { // minimumNumberOfEventsCheck
var myBool = false
var aString = "" // The text 1 string
var bString = "" // The text 2 string
var cString = "" // The recap string
if UserDefaults.standard.bool(forKey: kmultiRules) { // The user chose the dual rules option
let ruleSet = UserDefaults.standard.integer(forKey: kruleSelection) + 1
aString = "User chose 2 rules option"
bString = "User chose rule set # \(ruleSet)"
myBool = true
print("isDualRules true loop : generateStrings was called at \(Date().debugDescription)")
cString = "Dual rules option, user chose rule set nb \(ruleSet)"
}
else // The user chose the single rule option
{
aString = "User chose single rule option"
bString = "User had no choice : there is only one set of rules !"
myBool = false
print("isDualRules false loop : generateStrings was called at \(Date().debugDescription)")
cString = "Single rule option, user chose nothing."
}
return (aString, bString, cString, myBool)
} // End of func generatestrings() -> String
}
struct ContentView_Previews: PreviewProvider {
static var previews: some View {
return ContentView()
}
}
设置视图:
import SwiftUI
import UIKit
struct SettingsView: View {
@Environment(\.presentationMode) var presentationMode // in order to dismiss the Sheet
@State public var multiRules = UserDefaults.standard.bool(forKey: kmultiRules)
@State private var ruleSelection = UserDefaults.standard.integer(forKey: kruleSelection) // 0 is rule 1, 1 is rule 2
var body: some View {
NavigationView {
List {
Toggle(isOn: $multiRules)
{
Text("more than one rule ?")
}
.padding(.horizontal)
if multiRules {
Picker("", selection: $ruleSelection){
Text("rules 1").tag(0)
Text("rules 2").tag(1)
}.pickerStyle(SegmentedPickerStyle())
.padding(.horizontal)
}
} // End of List
.navigationBarItems(
leading:
Button("Done") {
self.saveDefaults() // We try to save once more if needed
self.presentationMode.wrappedValue.dismiss() // This dismisses the view
}
)
.navigationBarTitle("Settings", displayMode: .inline)
} // END of Navigation view
} // END of some View
func saveDefaults() {
UserDefaults.standard.set(multiRules, forKey: kmultiRules)
UserDefaults.standard.set(ruleSelection, forKey: kruleSelection)
}
}
// MARK: Preview struct
struct SettingsView_Previews: PreviewProvider {
static var previews: some View {
return SettingsView()
}
}
Constants.swift 文件:
import Foundation
import SwiftUI
let kmultiRules = "two rules"
let kruleSelection = "rules selection"
let kappStateChanged = "appStateChanged"
AppDelegate:
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
// Override point for customization after application launch.
UserDefaults.standard.register(defaults: [ // We initialize the UserDefaults
"two rules": false,
"rules selection": 0, // 0 is ruel 1, 1 is rule 2
"appStateChanged": false
])
return true
}
【问题讨论】:
-
让我们从问题的演示代码开始......
-
阅读并考虑此stackoverflow.com/help/minimal-reproducible-example 和此stackoverflow.com/help/how-to-ask。这不是一个“我们免费为您编写代码”的平台,而是一个“我们帮助您编写到目前为止所获得的代码”的平台。
-
嗯,我从不认为这个平台是一个“免费代码”场所。我总是提供清晰的代码来说明我的任何问题。我只是在这里寻找一个指针......我的应用程序的代码现在很长,我很难提取一个工作骨架来提供代码。明天将调查通知中心,这似乎对我的问题很有希望。
-
按照 Olaf 的建议,通过在 onDissappear 中触发通知中心方法来尝试通知中心方法,不高兴... .. 谢谢。 github.com/Esowes/refreshFromModal
标签: swiftui