我使用SwiftUI中的.fileImporter修饰符在我的应用程序中导入pdf文件。我有一些问题。首先,数据加载缓慢,通常无法加载,并显示消息Internal Error Cannot communication with a helper application。
但主要问题是,如果模态视图被向下滑动而忽略,它就无法再次呈现。可能是因为绑定的$showFileImporter没有重置。如果按下取消按钮以取消,则工作正常。我不知道是否有任何方法可以迫使它全屏来绕过这个问题。
这是我的代码:
.fileImporter(isPresented: $showFileImporter, allowedContentTypes: [.pdf]) { result in
switch result {
case .success(let url):
url.startAccessingSecurityScopedResource()
if let pDFDocument = PDFDocument(url: url) {
if let data = pDFDocument.dataRepresentation() {
// handle data
}
}
case .failure(let error):
print(error)
}
}
我可以确认我的.fileImporter在向下滑动时也不会重置isPresented绑定。一种确定的方法是将显示文件导入程序的按钮从$showFileImporter = true
更改为$showFileImporter.toggle()
。在滑动以关闭文件导入程序时,您必须按两次按钮才能再次显示。
不幸的是,这似乎是另一个半生不熟的SwiftUI,但我确实找到了一个合适的解决方案——用呈现按钮本身处理这个问题:
Button(action: {
if showFileImporter {
// NOTE: Fixes broken fileimporter sheet not resetting on swipedown
showFileImporter = false
DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
showFileImporter = true
})
} else {
showFileImporter = true
}
}, label: { ... })
我试着连续调用.thoggle()两次,但需要稍微延迟才能注册触发器。
编辑:我还注意到你没有打电话给url.stopAccessingSecurityScopedResource()
,你应该在打电话给你的pDFDocument
之后再打。
问题持续到2022年8月。我需要在多个地方实现Joseph Dvorak最出色的修复,因此将其抽象为任何等价的绑定:
// Usage
$showFileImporter.trampolineIfNeeded(to: true)
// Implementation
extension Binding where Value: Equatable {
func trampolineIfNeeded(to: Value, via: Value) {
if wrappedValue == to {
wrappedValue = via
DispatchQueue.main.asyncAfter(deadline: .now()+0.2, execute: {
wrappedValue = to
})
} else {
wrappedValue = to
}
}
}
extension Binding where Value == Bool {
func trampolineIfNeeded(to: Value) {
trampolineIfNeeded(to: to, via: !to)
}
}