SwiftUI DocumentGroup 和切换到后台
Posted
技术标签:
【中文标题】SwiftUI DocumentGroup 和切换到后台【英文标题】:SwiftUI DocumentGroup and switching to background 【发布时间】:2020-12-21 12:47:01 【问题描述】:我已经为“基于文档的应用程序”制作了一个基于新的 SwiftUI 多平台目标的应用程序。 但是,我面临着奇怪的问题。只要应用程序在前台,它就可以正常工作。如果通过任务切换将其移至后台,然后再次移至前台,则会将突变保存到文档中,但 SwiftUI 视图不会接收突变。因此,每当您在 UI 中按下一个按钮来改变文档时,当您从磁盘重新加载文档时,您会看到没有发生任何变化。
所以我在想,我使用 ObservedObjects,一旦我移动到后台,它们可能会被踢出内存。这可能是我的错误的原因吗?
但后来我在 App 结构中添加了一个打印行。
import SwiftUI
@main
struct MyApp: App
fileprivate func myLogging(_ file: FileDocumentConfiguration<MyDocument>) -> some View
print("""
IT IS CALLED
""")
return MainView().environmentObject(BindingWrapper(file.$document))
var body: some Scene
DocumentGroup(newDocument: MyDocument()) (file) in
return myLogging(file)
.commands AppCommands()
你猜怎么着......这个打印总是在一个突变被渲染之前执行。这是有道理的。因为file.$document
是一个绑定,如果你做了一个变异操作,绑定会警告苹果文件是脏的,但它也会使整个层次结构失效。一旦错误发生,此日志仍会打印!
所以在线 MainView().environmentObject(BindingWrapper(file.$document))
我假设一切都是从头开始创建的。 BindingWrapper 是一个自定义类,用于转换可观察对象中的绑定。这是我担心的对象之一,他们可能会被释放。但如果它们是新创建的……它们应该一直在那里,对吧?
顺便说一句,这个对象归环境所有。所以它不应该被释放。
所以,现在我被困住了。 Apple 是否对绑定 / ObservedObjects 进行了一些巧妙的缓存,即使我认为一切都是新创建的,也会将旧对象注入我的视图层次结构中?
【问题讨论】:
【参考方案1】:尝试将任何连线/实例化移动到文档组的第一个视图。如果该视图包含您希望共享文档窗口生命周期的 StateObject,它们将不会被重建。
在下面的示例中,一个 WindowStore 被容纳为一个 @StateObject,如所述。 App 中的 RootStore 创建了 WindowStore,其中包括自动售货服务并将其注册到托管的窗口数组中。两者都可以启用您的日志服务。 (对我来说,当@FocusedValue 失败时(即最顶层的文档不再是关键窗口),该数组可以帮助 WindowGroups 对特定文档进行操作。)
@main
struct ReferenceFileDoc: App
@StateObject var root: RootStore
var body: some Scene
DocumentGroup ProjectDocument() editor: doc in
DocumentGroupRoot(
window: root.makeWindowStore(doc.document),
factory: SwiftUIFactory(root, doc.document)
)
.environmentObject(doc.document)
.environment(\.documentURL, doc.fileURL)
.injectStores(from: root)
.commands Menus(root: root)
.... other scenes ...
struct DocumentGroupRoot: View
@EnvironmentObject var doc: ProjectDocument
@Environment(\.undoManager) var undoManager
@Environment(\.documentURL) var url
@StateObject var window: WindowStore
@StateObject var factory: UIFactory
var body: some View
passUndoManagerToDocument()
factory.reference(window)
return DocumentWindow(vm: factory.makeThisVM()) // Actual visible window
.focusedValue(\.keyWindow, window)
.focusedValue(\.keyDocument, doc)
.onAppear /// Tasks
.reportHostingNSWindow [weak window] in
window?.setWindow($0)
.onChange(of: url) [weak window] in window?.setFileURL($0)
.environmentObject(/// sub-state stores from WindowStore)
.environmentObject(window)
.environmentObject(factory)
【讨论】:
以上是关于SwiftUI DocumentGroup 和切换到后台的主要内容,如果未能解决你的问题,请参考以下文章
SwiftUI fileExporter 在 DocumentGroup 的工具栏修饰符中用作按钮修饰符时不存在
在 SwiftUI DocumentGroup macOS 中创建并打开一个新文档
如何使用 SwiftUI DocumentGroup 读取大文件而不制作临时副本?