core-data - 更新 NSHostingView 的关于单元重用的 SwiftUI 视图
问题描述
我有一个现有的 NSOutlineView,我想用一个接管整个 NSTableViewCell 的 SwiftUI 视图替换标准 UI 元素。当然,由于单元重用,我试图想出一种方法来更新 SwiftUI 视图,因为 outlineView 向下滚动......但我无法让它工作。SwiftUI 视图正确地渲染和显示它的元素,但在大多数情况下,它们显示的是错误的“人”的内容。这通常是标准 UIKit/AppKit 的简单单元重用问题,但在这种情况下,SwiftUI 视图由于某种原因没有更新。
举个例子,这是我为单元格制作的 SwiftUI 视图:
struct CJContactListCellView: View {
@ObservedObject var person: Person
var body: some View {
VStack(alignment: .leading, spacing: 8.0) {
CJContactProfileTop(person: person)
}
}
}
Person
是一个 NSManagedObject 子类,来自一个核心数据实体。这是我们滚动查看大纲视图时需要更新的内容。
为了创建和更新宿主视图,我创建了一个不同的类,它可以从 outlineView 单元类的 Objective-C 代码中调用:
@objc class CJContactsCellInterface: NSObject {
@ObservedObject var person: Person
var cellView: CJContactListCellView
@objc func makeContactsCellView() -> NSView{
self.cellView = CJContactListCellView(person: person)
return NSHostingView(rootView: self.cellView)
}
@objc func updatePersonForTagsView(person: Person) {
self.person = person
self.cellView.person = person // I thought this would update the SwiftUI view, but it doesn't
}
@objc init(person: Person) {
self.person = person
self.cellView = CJContactListCellView(person: person)
super.init()
}
}
在 outlineView 的 viewForTableColumn:item: 委托方法中,我实例化了 nib:
result = [outlineView makeViewWithIdentifier:@"ContactsCellSwiftUICell" owner:self];
[result setupCellViewWithPerson: person];
在NSTableCellView
视图类中,我person
在列表滚动时创建和更新对象:
- (void) setupCellViewWithPerson:(Person *)person {
if (self.tagsViewInterface == nil) {
self.tagsViewInterface = [[CJContactsTagsInterface alloc] initWithPerson: person];
NSView *tagsView = [self.tagsViewInterface makeContactsCellView];
tagsView.translatesAutoresizingMaskIntoConstraints = NO;
[self addSubview: tagsView];
[self addConstraint: [NSLayoutConstraint constraintWithItem: tagsView attribute:NSLayoutAttributeTop relatedBy:NSLayoutRelationEqual toItem:self.contactName attribute:NSLayoutAttributeBottom multiplier:1.0 constant: 8.0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: self attribute:NSLayoutAttributeBottom relatedBy:NSLayoutRelationEqual toItem:tagsView attribute:NSLayoutAttributeBottom multiplier:1.0 constant: 8.0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: self attribute:NSLayoutAttributeLeading relatedBy:NSLayoutRelationEqual toItem:tagsView attribute:NSLayoutAttributeLeading multiplier:1.0 constant: -8.0]];
[self addConstraint: [NSLayoutConstraint constraintWithItem: self attribute:NSLayoutAttributeTrailing relatedBy:NSLayoutRelationEqual toItem: tagsView attribute:NSLayoutAttributeTrailing multiplier:1.0 constant: 8.0]];
}
self.contactName.stringValue = person.displayName; // just used for debugging
[self.tagsViewInterface updatePersonForTagsViewWithPerson: person];
}
谁能指出我可能做错了什么?我希望由于我要替换Person
SwiftUI 视图中的对象,它会重新渲染整个视图;但我对组合和底层技术不太熟悉,所以可能有更好的方法来做到这一点。