当视图模型@Published 更改时,SwiftUI 列表因“NSRangeException”而崩溃
Posted
技术标签:
【中文标题】当视图模型@Published 更改时,SwiftUI 列表因“NSRangeException”而崩溃【英文标题】:SwiftUI List crashes with 'NSRangeException' when view model @Published changes 【发布时间】:2021-06-03 14:25:29 【问题描述】:第一个 ios 应用。如果 VM 中的 items
被替换为一个元素较少的数组,我会得到以下异常,放置异常断点不会提供任何有用的信息:
*** 由于未捕获的异常“NSRangeException”而终止应用程序,原因:“索引 (1176) 超出范围 (1176)”
查看:
struct LibrarySongsPageView: View
@StateObject var viewModel = LibrarySongsViewModel()
var body: some View
print(viewModel.items.count)
return List(viewModel.items, id: \.persistentID) mediaItem in
HStack
if let art = mediaItem.artwork, let uiImg = art.image(at: CGSize(width: 60, height: 60))
Image(uiImage: uiImg)
.toIcon()
.padding(.trailing)
else
Image(systemName: "music.note")
Text(mediaItem.title ?? "Unknown")
.font(.title2)
.navigationTitle("Songs")
虚拟机:
class BaseLibraryViewModel: ObservableObject
let provider = LibraryProvider.instance
@Published var items = [MPMediaItem]()
let sortOrder = SortOrder.title
var subscription: AnyCancellable!
init()
subscription = provider.setActive(active: true, type: .songs)!.sink [weak self] items in
self?.items = items
class LibrarySongsViewModel: BaseLibraryViewModel
我已经通过将正文的第一行更改为:
return List(viewModel.items.indices, id: \.self) index in
let mediaItem = viewModel.items[index]
但我不知道为什么第一个版本会产生异常。当访问视图body
属性时,我检查了viewModel.items.count
和po viewModel.items
,它看起来数组是更新后的数组,比我预期的前一个项目少一个,但在@987654328 期间仍然抛出异常@访问。
谁能解释一下?
【问题讨论】:
【参考方案1】:我猜是并发问题。
在订阅中的.sink
之前,输入.receiveOn(DispatchQueue.main)
【讨论】:
我现在有.receiveOn(DispatchQueue.main)
,但它没有帮助。使用相同的数组也可以修复它,例如接收器中的self?.items.removeAll(keepingCapacity: true); self?.items.append(contentsOf: items)
。不知道为什么它不喜欢切换数组。
这很奇怪,因为您似乎没有尝试访问索引越界的东西,如果这一切都发生在 main 上,我也不明白为什么会这样。除非在上面未包含的某处添加了其他东西?以上是关于当视图模型@Published 更改时,SwiftUI 列表因“NSRangeException”而崩溃的主要内容,如果未能解决你的问题,请参考以下文章
当从另一个 ObservedObject 链接到 Published 属性时,视图不会对更改做出反应
SwiftUI @Published 属性正在 DetailView 中更新
Swift - 如何从视图之外的 func 访问@Published var?
来自 @Published 属性的 SwiftUI 动画从视图外部更改