简体   繁体   English

SwiftUI:未调用@StateObject deinit?

[英]SwiftUI: @StateObject deinit NOT called?

I have the following code:我有以下代码:

struct ContentView: View {
    @Environment(\.managedObjectContext) private var viewContext

    @FetchRequest(
        sortDescriptors: [NSSortDescriptor(keyPath: \Item.timestamp, ascending: true)],
        animation: .default)
    private var items: FetchedResults<Item>

    var body: some View {
        NavigationView {
            List {
                ForEach(items) { item in
                    NavigationLink {
                        Text("Item at \(item.timestamp!, formatter: itemFormatter)")
                    } label: {
//                        Text(item.timestamp!, formatter: itemFormatter)
                        ItemCellView(model: ItemCellViewModel(item: item))
                    }
                }
                .onDelete(perform: deleteItems)
            }
            .toolbar {
                ToolbarItem(placement: .navigationBarTrailing) {
                    EditButton()
                }
                ToolbarItem {
                    Button(action: addItem) {
                        Label("Add Item", systemImage: "plus")
                    }
                }
            }
            Text("Select an item")
        }
    }

    private func addItem() {
        withAnimation {
            let newItem = Item(context: viewContext)
            newItem.timestamp = Date()

            do {
                try viewContext.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }

    private func deleteItems(offsets: IndexSet) {
        withAnimation {
            offsets.map { items[$0] }.forEach(viewContext.delete)

            do {
                try viewContext.save()
            } catch {
                // Replace this implementation with code to handle the error appropriately.
                // fatalError() causes the application to generate a crash log and terminate. You should not use this function in a shipping application, although it may be useful during development.
                let nsError = error as NSError
                fatalError("Unresolved error \(nsError), \(nsError.userInfo)")
            }
        }
    }
}

private let itemFormatter: DateFormatter = {
    let formatter = DateFormatter()
    formatter.dateStyle = .short
    formatter.timeStyle = .medium
    return formatter
}()

struct ContentView_Previews: PreviewProvider {
    static var previews: some View {
        ContentView().environment(\.managedObjectContext, PersistenceController.preview.container.viewContext)
    }
}


struct ItemCellView: View {
    
    @StateObject var model:ItemCellViewModel
    
    var body: some View {
        
        Text(model.item.timestamp!, formatter: itemFormatter)
            .foregroundColor(.blue)
    }
    
}

class ItemCellViewModel: ObservableObject {
    
    @Published var item:Item
    
    init(item:Item) {
        self.item = item
    }
    
    deinit {
        print("ItemCellViewModel EDINIT \(self)")
    }
    
}

It draws this:它画了这个:

在此处输入图像描述

PROBLEM:问题:

ItemCellViewModel deinit is NOT called after I swipe to delete the item.在我滑动删除项目后,不会调用ItemCellViewModel deinit。 Can someone tell me why the ItemCellViewModel sticks around even after the ItemCellView is gone?有人能告诉我为什么即使在ItemCellViewModel消失后ItemCellView仍然存在吗?

This is a simplified version of a codebase I am working in. I need that model to go away when the view is "deleted" by the user.这是我正在使用的代码库的简化版本。当用户“删除”视图时,我需要 model 到 go。 Why is SwiftUI keeping ItemCellViewModel around??为什么 SwiftUI 保留ItemCellViewModel

View is not deleted in a fact (just removed from visible area) because List caches some number of views (visible area + ~2) and StateObject is persistent storage of view which keeps its state. So observed behavior is by-design.事实上,View 并没有被删除(只是从可见区域中删除),因为 List 缓存了一些视图(可见区域 + ~2),而 StateObject 是视图的持久存储,它保持其 state。因此观察到的行为是设计使然。

Get rid of the view model object, in SwiftUI we use value types and the View struct is the view model that SwiftUI uses to create and update UIKit/AppKit views on our behalf.摆脱视图 model object,在 SwiftUI 中我们使用值类型,视图结构是视图 model,SwiftUI 代表我们使用它来创建和更新 UIKit/AppKit 视图。 Learn this in SwiftUI Essentials WWDC 2019 .SwiftUI Essentials WWDC 2019中了解这一点。 Also you can't nest an ObservableObject inside an ObservableObject either.此外,您也不能将 ObservableObject 嵌套在 ObservableObject 中。 To fix this change the ItemCellView to this:要解决此问题,请将 ItemCellView 更改为:

struct ItemCellView: View {
    
    @ObservedObject var item: Item
    
    var body: some View {
        
        Text(item.timestamp!, formatter: itemFormatter)
            .foregroundColor(.blue)
    }
    
}

声明:本站的技术帖子网页,遵循CC BY-SA 4.0协议,如果您需要转载,请注明本站网址或者原文地址。任何问题请咨询:yoyou2525@163.com.

 
粤ICP备18138465号  © 2020-2024 STACKOOM.COM