切换 属性 不会实时显示变化
Toggling Property Does Not Show Change in Real Time
我有一个星形按钮,我想在点击时在填充和空之间切换。
我实现了以下功能:
func setStarButton() {
let currentItem = data[currentItemIndex!]
if currentItem.isStarred == true {
starButton.setImage(UIImage(systemName: "star.fill"), for: .normal)
}
else {
starButton.setImage(UIImage(systemName: "star"), for: .normal)
}
}
@IBAction func starTapped(_ sender: Any) {
// Change the property in the Array
var currentItem = item[currentItemIndex!]
currentItem.isStarred?.toggle()
// Update the database
model.updateStarredStatus(currentItem.docID!, currentItem.isStarred!)
// Update the button
setStarButton()
}
然后我在 viewDidAppear 中调用该函数:
override func viewDidAppear(_ animated: Bool) {
// Set the status of the star button
setStarButton()
}
因此发生了以下预期行为:
- 只有当我第一次打开视图控制器时,星号按钮才显示为正确的filled/unfilled状态
- 当我点击星形按钮时,我的 Firebase Firestore 数据库会更新 Bool 值
我想要实现的目标:当我继续实时点击星形按钮时,它会在视图中变为 filled/unfilled。
有什么想法吗?我想我可能需要视图来监听数据库中的更改以进行视觉更新,但我不确定。非常感谢任何指导!
您的 item
数组包含结构。 Swift 中的结构是值类型。当您说 var currentItem = item[currentItemIndex!]
时,您有效地将结构的副本分配给 currentItem
。然后在函数 returns.
时修改并丢弃此副本
稍后,当您在 setStarButton
中访问 data[currentItemIndex!]
时,您将访问原始的、未修改的结构。从 Firebase 刷新数组后,您会看到正确的值。
一个简单的避免问题的方法就是去掉局部变量currentItem
,直接对数组中的struct进行操作
就我个人而言,我会将相关值传递给 setStarred
;这样你就消除了访问 items 数组的重复代码。您还应该尽可能避免强制展开。对于 isStarred
和 docID
之类的可选属性也没有多大意义 - 一个项目要么加星标,要么不加星标。默认值 false
比 nil
更有意义。来自 Firebase 的所有文档都会有一个 docID
func setStarButton(starred: Bool) {
let imageName = starred ? "star.fill" : "star"
starButton.setImage(UIImage(systemName: imageName), for: .normal)
}
@IBAction func starTapped(_ sender: Any) {
guard itemIndex = self.currentItemIndex else {
return
}
var isStarred = item[itemIndex].isStarred ?? false
isStarred.toggle()
item[itemIndex].isStarred = isStarred
// Update the database
model.updateStarredStatus(currentItem.docID!, isStarred)
// Update the button
setStarButton(starred: isStarred)
}
override func viewDidAppear(_ animated: Bool) {
// Set the status of the star button
if let itemIndex = self.currentItemIndex {
setStarButton(starred: self.item[itemIndex].isStarred ?? false)
}
}
我有一个星形按钮,我想在点击时在填充和空之间切换。
我实现了以下功能:
func setStarButton() {
let currentItem = data[currentItemIndex!]
if currentItem.isStarred == true {
starButton.setImage(UIImage(systemName: "star.fill"), for: .normal)
}
else {
starButton.setImage(UIImage(systemName: "star"), for: .normal)
}
}
@IBAction func starTapped(_ sender: Any) {
// Change the property in the Array
var currentItem = item[currentItemIndex!]
currentItem.isStarred?.toggle()
// Update the database
model.updateStarredStatus(currentItem.docID!, currentItem.isStarred!)
// Update the button
setStarButton()
}
然后我在 viewDidAppear 中调用该函数:
override func viewDidAppear(_ animated: Bool) {
// Set the status of the star button
setStarButton()
}
因此发生了以下预期行为:
- 只有当我第一次打开视图控制器时,星号按钮才显示为正确的filled/unfilled状态
- 当我点击星形按钮时,我的 Firebase Firestore 数据库会更新 Bool 值
我想要实现的目标:当我继续实时点击星形按钮时,它会在视图中变为 filled/unfilled。
有什么想法吗?我想我可能需要视图来监听数据库中的更改以进行视觉更新,但我不确定。非常感谢任何指导!
您的 item
数组包含结构。 Swift 中的结构是值类型。当您说 var currentItem = item[currentItemIndex!]
时,您有效地将结构的副本分配给 currentItem
。然后在函数 returns.
稍后,当您在 setStarButton
中访问 data[currentItemIndex!]
时,您将访问原始的、未修改的结构。从 Firebase 刷新数组后,您会看到正确的值。
一个简单的避免问题的方法就是去掉局部变量currentItem
,直接对数组中的struct进行操作
就我个人而言,我会将相关值传递给 setStarred
;这样你就消除了访问 items 数组的重复代码。您还应该尽可能避免强制展开。对于 isStarred
和 docID
之类的可选属性也没有多大意义 - 一个项目要么加星标,要么不加星标。默认值 false
比 nil
更有意义。来自 Firebase 的所有文档都会有一个 docID
func setStarButton(starred: Bool) {
let imageName = starred ? "star.fill" : "star"
starButton.setImage(UIImage(systemName: imageName), for: .normal)
}
@IBAction func starTapped(_ sender: Any) {
guard itemIndex = self.currentItemIndex else {
return
}
var isStarred = item[itemIndex].isStarred ?? false
isStarred.toggle()
item[itemIndex].isStarred = isStarred
// Update the database
model.updateStarredStatus(currentItem.docID!, isStarred)
// Update the button
setStarButton(starred: isStarred)
}
override func viewDidAppear(_ animated: Bool) {
// Set the status of the star button
if let itemIndex = self.currentItemIndex {
setStarButton(starred: self.item[itemIndex].isStarred ?? false)
}
}