1

我正在关注SwiftUI 的 100 天,并已达到第 37 天。在使用 UserDefaults 进行永久更改时,我遇到了didSet.

(我在 iOS 13.4 中使用 Swift 5)

在示例代码中,它写道

.navigationBarItems(trailing: Button("Save") {
    if let actualAmount = Int(self.amount) {
        let item = ExpenseItem(name: self.name, type: self.type, amount: actualAmount)
        self.expenses.items.append(item)
    }
})

didSet应该在哪里调用.append()

但是,在实践中,didSet除非我将上面的代码更改为

.navigationBarItems(trailing: Button("Save") {
    if let actualAmount = Int(self.amount) {
        let item = ExpenseItem(name: self.name, type: self.type, amount: actualAmount)
        let newItems = self.expenses.items + [item]
        self.expenses.items = newItems
    }
})

我还在 Playground 中编写了一个小测试(见下文),这表明它.append()didSet

struct Count {
    var array: [Int] {
        didSet {
            print("struct Count - didSet() called")
        }
    }
}
class CountClass {
    var array: [Int] {
        didSet {
            print("class CountClass - didSet() called")
        }
    }
    init() {
        array = [1, 2, 3]
    }
}
struct Test {
    var countA = Count(array: [1, 2, 3])
    var countB = CountClass()

    mutating func testDidSet() {
        countA.array.append(4)
        countB.array.append(4)
    }
}

var t = Test()
t.testDidSet()

这种奇怪的行为真的让我想知道它是如何didSet工作的。还是这个问题与使用有关@ObservedObject(示例项目就是这种情况)?

PS:我从Project7下载了汉化版,也有这个问题。

4

4 回答 4

4

这是一个已知的 Swift 5.2 错误:在修改时不会调用包装属性的观察者 ( https://bugs.swift.org/browse/SR-12089 )。他们从一月份就知道了这一点,并且同样发布了一个更新,破坏了一堆生产代码¯\_(ツ)_/¯

问题中已经提出了一个临时解决方法 - 属性重新分配而不是修改。

于 2020-04-04T02:18:34.757 回答
0

发生的事情是 Swift 没有识别.append()设置变量。您可以通过将数组复制到新的临时数组、附加新值然后将类数组设置为此临时数组来解决此问题。

var newActivityList = [Activity]() //new temporary array
for activity in self.activityList.activities {
    newActivityList.append(activity) //copy class array to temp array
}
newActivityList.append(newActivity) //append new value

self.activityList.activities = newActivityList //set class array to temp array

PS:上面的例子是第47天,但逻辑是一样的。

于 2020-03-31T01:25:40.493 回答
0

我也经历了这个项目。确保您itemsExpenses班级中的财产被标记为@Published。如下;

import SwiftUI

struct ExpenseItem: Identifiable, Codable {
let id = UUID()
let name: String
let type: String
let amount: Int
}

class Expenses: ObservableObject {
init() {
    if let items = UserDefaults.standard.data(forKey: "Items") {
        let decoder = JSONDecoder()
        if let decoded = try? decoder.decode([ExpenseItem].self, from: items)     {
            self.items = decoded
            return
        }
    }
    self.items = []
}


@Published var items: [ExpenseItem] {
    didSet {
        let encoder = JSONEncoder()
        if let encoded = try? encoder.encode(items) {
            UserDefaults.standard.set(encoded, forKey: "Items")
        }
    }
}
}

self.presentationMode.wrappedValue.dismiss()在您的导航栏中添加保存按钮。

.navigationBarItems(trailing: Button("Save") {
            if let actualAmount = Int(self.amount) {
                let item = ExpenseItem(name: self.name, type: self.type,   amount: actualAmount)
                self.expenses.items.append(item)
                self.presentationMode.wrappedValue.dismiss()
            } else {
                self.isShowingAlert = true
            }

        })
于 2020-03-29T17:11:19.960 回答
0

我想我上周完成了这个项目,但查看Swift GitHub 页面,似乎 24 日有更新。

当我做这个项目时,一切都很好,但现在我在第 47 天,我遇到了这个问题。也许它与 Swift 5.2 更新有关。

于 2020-03-30T23:57:31.583 回答