说我有UserSettings
EnviornmentObject
,它的属性之一是一个类,问题是当我更改该类的值时,EnviornmentObject
将不会发布这些更改。我知道为什么,但是似乎找不到解决方法。
下面是显示问题的简化代码:
struct TestView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
ZStack {
Text("test: \(self.settings.ob.val)")
VStack {
// This is the only one that works and that makes sense, it changes the entire object
Button(action: {
self.settings.changeOb(to: testOb(val: "1"))
}) {
Text("Change object")
}
// From here on nothing works, I tried different ways to change the object value
Button(action: {
self.settings.ob.changeVal(to: "2")
}) {
Text("Change object's val")
}
Button(action: {
self.settings.changeVal(to: "3")
}) {
Text("Change object's val V2")
}
Spacer()
}
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
return ZStack {
TestView().environmentObject(UserSettings(ob: testOb("abc")))
}
}
}
class testOb: ObservableObject {
@Published private(set) var val: String
init(val: String) {
self.val = val
}
func changeVal(to: String) {
self.val = to
}
}
class UserSettings: ObservableObject {
@Published private(set) var ob: testOb
init(ob: testOb) {
self.ob = ob
}
func changeOb(ob: testOb) {
self.ob = ob
}
func changeVal(to: String) {
self.ob.val(to: to)
}
}
答案 0 :(得分:1)
尝试这样的事情:
git rev-list $BASE..$HEAD | \
xargs -L1 sh -c 'lines=$(git show --name-only $0 | grep -e somewhere/a -e somewhere/b | wc -l); \
test $lines -ne 1 || { echo "bad commit $0"; false; }'
class UserSettings: ObservableObject {
@Published var ob: testOb{
willSet{
observer.cancel()
}
didSet{
observer = ob.objectWillChange.sink(){self.objectWillChange.send()}
}
}
var observer: AnyCancellable!
init(ob: testOb) {
self.ob = ob
self.observer = nil
self.observer = ob.objectWillChange.sink(){self.objectWillChange.send()}
}
func sendChange(){
}
func changeOb(ob: testOb) {
self.ob = ob
}
func changeVal(to: String) {
self.ob.changeVal(to: to)
}
deinit {
observer.cancel()
}
}
用于发送通知,而不用于收听。
或者您可以在子对象中存储到父对象的弱链接,并在子对象的@Published
中调用parent.objectWillChange.send()
。
答案 1 :(得分:0)
我终于能够解决它,问题是苹果不支持嵌套的ObesrvableObject
以及许多重要功能(这很可惜,但无论如何),但是据我所知,这已经在他们的议程上了。
解决方案是,每次对象更改时,我都必须手动通知,这可能会让您拥有更多的对象感到痛苦。
要进行通知,我们首先需要导入Combine
,以便我们可以使用负责通知的AnyCancellable
。
这是更新的代码:
// FIRST CHANGE
import Combine
struct TestView: View {
@EnvironmentObject var settings: UserSettings
var body: some View {
ZStack {
Text("test: \(self.settings.ob.val)")
VStack {
// This is the only one that works and that makes sense, it changes the entire object
Button(action: {
self.settings.changeOb(to: testOb(val: "1"))
}) {
Text("Change object")
}
// From here on nothing works, I tried different ways to change the object value
Button(action: {
self.settings.ob.changeVal(to: "2")
}) {
Text("Change object's val")
}
Button(action: {
self.settings.changeVal(to: "3")
}) {
Text("Change object's val V2")
}
Spacer()
}
}
}
}
struct TestView_Previews: PreviewProvider {
static var previews: some View {
return ZStack {
TestView().environmentObject(UserSettings(ob: testOb("abc")))
}
}
}
class testOb: ObservableObject {
@Published private(set) var val: String
init(val: String) {
self.val = val
}
func changeVal(to: String) {
self.val = to
}
}
class UserSettings: ObservableObject {
@Published private(set) var ob: testOb
// SECOND CHANGE, this is responsible to notify on changes
var anyCancellable: AnyCancellable? = nil
init(ob: testOb) {
self.ob = ob
// THIRD CHANGE, initialize our notifier
anyCancellable = self.ob.objectWillChange.sink { (_) in
self.objectWillChange.send()
}
}
func changeOb(ob: testOb) {
self.ob = ob
}
func changeVal(to: String) {
self.ob.val(to: to)
}
}