SwiftUI .fileImporter 向下滑动关闭后无法再次显示

问题描述 投票:0回答:3

我正在 SwiftUI 中使用 .fileImporter 修饰符在我的应用程序中导入 pdf 文件。 我有几个问题。 首先,数据加载速度很慢,并且通常无法加载并给出消息“内部错误无法与帮助程序应用程序通信”。

但主要问题是,如果向下滑动关闭模态视图,则无法再次呈现。 大概是因为绑定 $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)
        }
    }
ios xcode swiftui swiftui-fileimporter
3个回答
12
投票

我可以确认我的 .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: { ... })

我尝试连续调用 .toggle() 两次,但需要稍微延迟触发器才能注册。

编辑: 我还注意到您没有致电

url.stopAccessingSecurityScopedResource()
,您应该在致电您的
pDFDocument
后才拨打。


0
投票

截至 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)
    }
}

0
投票

对于 2024 年之后寻找此产品的任何人:

您可以使用 .onChange 修饰符来确定选择器是否被关闭。

示例:

    .fileImporter(isPresented: $isImporting, allowedContentTypes: [.mp3, .wav, .midi], onCompletion: {...}
    .onChange(of: isImporting) { oldValue, newValue in
        print("Picker state = \(oldValue) -> \(newValue)")
    }
© www.soinside.com 2019 - 2024. All rights reserved.