@@ -78,6 +78,12 @@ struct DetailView: View {
7878 /// 编辑模式右侧实时预览的内容(防抖更新,避免每次击键都全量渲染)
7979 @State private var previewContent : String = " "
8080
81+ /// 分栏预览 WebView 自身的 WebPage 引用。
82+ /// 不与渲染模式的 `exportedPage` 共享:预览 WebView 移除/重建时不应影响渲染模式
83+ /// 仍持有的 WebPage,避免两者在切模式/切分栏的过渡窗口争抢同一绑定导致 use-after-free。
84+ /// Raw 模式 PDF 导出走独立 HTML 路径,不读取此绑定。
85+ @State private var previewExportedPage : WebPage ?
86+
8187
8288 var body : some View {
8389 VStack ( spacing: 0 ) {
@@ -652,7 +658,7 @@ struct DetailView: View {
652658
653659 // 渲染模式视图 — 仅在渲染模式下显示(渲染模式布局保持不变)
654660 if documentViewModel. displayMode == . rendered {
655- webMarkdownView ( content: documentViewModel. content)
661+ webMarkdownView ( content: documentViewModel. content, exportedPage : $exportedPage )
656662 }
657663 }
658664 . frame ( maxWidth: . infinity, maxHeight: . infinity)
@@ -686,7 +692,7 @@ struct DetailView: View {
686692 if documentViewModel. displayMode == . raw && !documentViewModel. isPlainTextMode && appViewModel. isSplitPreviewEnabled {
687693 Rectangle ( ) . fill ( themeColors. border) . frame ( width: 1 )
688694
689- webMarkdownView ( content: previewContent)
695+ webMarkdownView ( content: previewContent, exportedPage : $previewExportedPage )
690696 . frame ( maxWidth: . infinity, maxHeight: . infinity)
691697 }
692698 }
@@ -703,9 +709,12 @@ struct DetailView: View {
703709 previewContent = documentViewModel. content
704710 }
705711 . task ( id: documentViewModel. content) {
706- // 击键防抖:停顿 200ms 无新输入后再刷新右侧预览
712+ // 击键防抖:停顿 200ms 无新输入后再刷新右侧预览。
713+ // 分栏已关闭时不写 previewContent:避免对已拆毁的预览 WebView 触发无谓重算,
714+ // 也避免与视图树拆毁竞态。
707715 try ? await Task . sleep ( for: . milliseconds( 200 ) )
708716 guard !Task. isCancelled else { return }
717+ guard appViewModel. isSplitPreviewEnabled else { return }
709718 previewContent = documentViewModel. content
710719 }
711720 . overlay ( alignment: . topTrailing) {
@@ -739,7 +748,7 @@ struct DetailView: View {
739748
740749 /// 渲染视图(渲染模式全宽显示 / 编辑模式右栏实时预览共用)
741750 @ViewBuilder
742- private func webMarkdownView( content: String ) -> some View {
751+ private func webMarkdownView( content: String , exportedPage : Binding < WebPage ? > ) -> some View {
743752 WebViewMarkdownView (
744753 content: content,
745754 fileURL: documentViewModel. currentFileURL,
@@ -767,7 +776,7 @@ struct DetailView: View {
767776 onOpenLinkedMarkdownFile: { [ weak session] url in
768777 session? . handleLinkedMarkdownFile ( url. standardizedFileURL)
769778 } ,
770- exportedPage: $ exportedPage
779+ exportedPage: exportedPage
771780 )
772781 . onChange ( of: documentViewModel. scrollToLineRequest) { _, newValue in
773782 if newValue != nil {
0 commit comments