当视图模型@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.countpo 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 动画从视图外部更改

如果操作未立即完成,则 SwiftUI 视图在绑定到 @Published var 时没有动画

SwiftUI - 尽管使用了 @Published 和 @ObservedObject,但视图不会更新