SwiftUI 列表未使用 ForEach 正确更新
Posted
技术标签:
【中文标题】SwiftUI 列表未使用 ForEach 正确更新【英文标题】:SwiftUI List Not Updating Correctly with ForEach 【发布时间】:2020-05-27 16:39:46 【问题描述】:我正在尝试使用带有两个 ForEach 循环的列表来创建收藏夹功能。当我单击按钮时,项目移动到正确的部分,但按钮图像和功能没有更新。我有什么遗漏或做错了吗?
如果我导航到另一个视图并返回,列表最初会正确呈现,但如果我单击按钮仍会显示相同的行为。
如果我使用两个具有完全相同设置的单独列表,一切正常,但在 UI 中看起来很奇怪,因为即使列表中没有项目,每个列表也占用相同数量的空间。
或者,有没有办法强制列表重绘作为按钮点击的一部分?
谢谢!
import SwiftUI
struct BusinessListView: View
@EnvironmentObject var state: ApplicationState
var body: some View
VStack
List
Section(header: Text("Favorites"))
if(state.favorites.count == 0)
Text("No Favorites")
else
ForEach(state.favorites, id: \.self) favorite in
HStack
Button(
action: ,
label: Image(systemName: "heart.fill").foregroundColor(.red)
)
.onTapGesture self.toggleFavorite(business: favorite)
Text("\(favorite.name)")
Section(header: Text("Other Businesses"))
ForEach(state.others, id: \.self) business in
HStack
Button(
action: ,
label: Image(systemName: "heart")
)
.onTapGesture self.toggleFavorite(business: business)
Text("\(business.name)")
func toggleFavorite(business: Business)
if(state.favorites.contains(business))
self.state.favorites = self.state.favorites.filter $0 != business
self.state.others.append(business)
else
self.state.others = self.state.others.filter $0 != business
self.state.favorites.append(business)
sortBusinesses()
func sortBusinesses()
self.state.favorites.sort
$0.name < $1.name
self.state.others.sort
$0.name < $1.name
【问题讨论】:
如果你给我们一个可重现的可编译的例子会很棒......***.com/help/minimal-reproducible-example @Chris - 如果您想看一下,这里是完整的代码。除了目前,它并没有做很多事情。 github.com/benbaran/tippler 。我将尝试创建一个不需要进行网络调用等的示例。 @Chris - 这是一个最小的可重现示例:github.com/benbaran/swift-ui-favorites-list。 期待回答 -> 我已经更正了 @Chris - 感谢您的帮助!但是,上面的答案实际上并不起作用。项目移动时,动作和图标不会改变。它看起来就是这样,因为 toggleFavorite() 方法将处理这两种情况。 【参考方案1】:更新的答案,有效,但是...
1) 诀窍是每当您将“单元格”从收藏更改为非收藏时更改 id -> 我假设 Apple 使用 UITableView - 逻辑与 dequeueResubleCell 并且如果 id 相同,则不会更新,而只是重复使用/复制,因此心脏没有改变
2) 我现在在收藏夹更改时随机更改 id - 你必须在那里考虑一个更好/更清洁的解决方案。
struct BusinessListView: View
@EnvironmentObject var state: ApplicationState
var body: some View
VStack
List
Section(header: Text("Favorites"))
if(state.favorites.count == 0)
Text("No Favorites")
else
ForEach(state.favorites, id: \.self) favorite in
HStack
Button(
action:
self.toggleFavorite(business: favorite)
,
label:
HStack
Image(systemName: "heart.fill").foregroundColor(.red)
Text("\(favorite.name)")
).id(favorite.id)
Section(header: Text("Other Businesses"))
ForEach(state.others, id: \.self) business in
HStack
Button(
action:
self.toggleFavorite(business: business)
,
label:
HStack
Image(systemName: "heart")
Text("\(business.name)")
)
.id(business.id)
func toggleFavorite(business: Business)
if(state.favorites.contains(business))
self.state.favorites = self.state.favorites.filter $0 != business
self.state.others.append(business)
if let index = self.state.others.index(of: business)
self.state.others[index].id = Int.random(in: 10000...50000)
else
self.state.others = self.state.others.filter $0 != business
self.state.favorites.append(business)
if let index = self.state.favorites.index(of: business)
self.state.favorites[index].id = Int.random(in: 10000...50000)
sortBusinesses()
func sortBusinesses()
self.state.favorites.sort
$0.name < $1.name
self.state.others.sort
$0.name < $1.name
【讨论】:
嗯。这似乎对我也不起作用。你能看一下最小的例子吗?我在其中看到的是,即使在列表项移动之后,动作和颜色也会保持不变。也许我只是在某个地方犯了一个愚蠢的错误? 你指的是什么颜色? 心应该变成一个充满红色的心。 基本上我看到的行为是该项目移动到收藏夹部分,但图标和操作没有改变。如果我导航到另一个视图并返回,它会正确更新。 谢谢!!!我觉得 SwiftUI 应该处理这种情况。我将发布到开发者论坛,看看他们是否有兴趣修复它:)【参考方案2】:您是否确认.onTapGesture
正在被呼叫?或者,您可以将self.toggleFavorite(business: favorite)
放在按钮的操作内。
Button(
action: self.toggleFavorite(business: business) ,
label: Image(systemName: "heart")
)
【讨论】:
是的,如果我添加一个打印语句,我可以看到它被调用了。但它始终是添加收藏按钮的 onTapGesture。以上是关于SwiftUI 列表未使用 ForEach 正确更新的主要内容,如果未能解决你的问题,请参考以下文章
在 NavigationView 中清除 SwiftUI 列表未正确返回默认值
带有 Xcode 11 beta 7 的 SwiftUI 未更新 List / ForEach 的内容
如果列表行在 SwiftUI 中包含文本字段,则无法从 foreach 中删除元素