MACOS 上带有 Catalyst 的 UIDocumentPickerViewController
UIDocumentPickerViewController with Catalyst on MACOS
我有在 MacOS 中使用 Catalyst 显示选择器的代码:
final class DocumentPicker: NSObject, UIViewControllerRepresentable, ObservableObject {
typealias UIViewControllerType = UIDocumentPickerViewController
@Published var urlsPicked = [URL]()
lazy var viewController:UIDocumentPickerViewController = {
// For picked only folder
let vc = UIDocumentPickerViewController(documentTypes: ["public.folder"], in: .open)
vc.allowsMultipleSelection = false
vc.delegate = self
return vc
}()
........
和:
struct ContentView: View {
@ObservedObject var picker = DocumentPicker()
@State private var urlPick = ""
var body: some View {
HStack {
Text(urlPicked())
.padding()
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.white, lineWidth: 1)
)
TextField("", text: $urlPick)
.textFieldStyle(RoundedBorderTextFieldStyle())
.font(.system(size: 10))
.disabled(true)
Spacer()
Button(action: {
#if targetEnvironment(macCatalyst)
let viewController = UIApplication.shared.windows[0].rootViewController!
viewController.present(self.picker.viewController, animated: true)
self.picker.objectWillChange.send()
#endif
print("Hai premuto il pulsante per determinare il path della GeoFolder")
}) {
Image(systemName: "square.and.arrow.up")
}
}
.padding()
}
private func urlPicked() -> String {
var urlP = ""
if picker.urlsPicked.count > 0 {
urlP = picker.urlsPicked[0].path
urlPick = picker.urlsPicked[0].path
}
return urlP
}
}
如果我 运行 上面的代码我在 text
中得到了选择的正确路径,而在 textfield
中什么都没有并且我在 urlPick = picker.urlsPicked[0].path
中也有错误:Modifying state during view update, this will cause undefined behavior.
我如何修改代码以显示也在 textfield
?
中选择的正确路径
have the error in urlPick = picker.urlsPicked[0].path: Modifying state
during view update, this will cause undefined behavior. How can I
modify the code to show the correct path chosen also in textfield?
尝试以下方法
if picker.urlsPicked.count > 0 {
urlP = picker.urlsPicked[0].path
DispatchQueue.main.async {
urlPick = picker.urlsPicked[0].path
}
}
任何想要创建具有只读权限的 MacOS 文档选择器的人,请使用以下解决方案:
import Foundation
import UIKit
extension ViewController: UIDocumentBrowserViewControllerDelegate, UIDocumentPickerDelegate {
@objc func presentDocumentPicker() {
if operatingSystem == .macintosh {
let documentPicker = UIDocumentBrowserViewController(forOpening: [.pdf])
documentPicker.delegate = self
documentPicker.allowsDocumentCreation = false
documentPicker.allowsPickingMultipleItems = false
// Present the document picker.
present(documentPicker, animated: true, completion: nil)
} else {
let documentsPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.pdf])
documentsPicker.delegate = self
documentsPicker.allowsMultipleSelection = false
documentsPicker.modalPresentationStyle = .fullScreen
self.present(documentsPicker, animated: true, completion: nil)
}
}
func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
guard let url = documentURLs.first, url.startAccessingSecurityScopedResource() else { return }
defer {
DispatchQueue.main.async {
url.stopAccessingSecurityScopedResource()
}
}
debugPrint("[DocumentPicker] Selected Item with URL : ", url)
controller.dismiss(animated: true)
}
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first, url.startAccessingSecurityScopedResource() else { return }
defer {
DispatchQueue.main.async {
url.stopAccessingSecurityScopedResource()
}
}
debugPrint("[DocumentPicker] Selected Item with URL : ", url)
controller.dismiss(animated: true)
}
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
controller.dismiss(animated: true)
}
}
请注意,如果权利是可读写的(即您还允许用户将文件保存到计算机)- 那么您可以简单地使用 UIDocumentPicker(我的代码段中的非 .macintosh 示例).
我有在 MacOS 中使用 Catalyst 显示选择器的代码:
final class DocumentPicker: NSObject, UIViewControllerRepresentable, ObservableObject {
typealias UIViewControllerType = UIDocumentPickerViewController
@Published var urlsPicked = [URL]()
lazy var viewController:UIDocumentPickerViewController = {
// For picked only folder
let vc = UIDocumentPickerViewController(documentTypes: ["public.folder"], in: .open)
vc.allowsMultipleSelection = false
vc.delegate = self
return vc
}()
........
和:
struct ContentView: View {
@ObservedObject var picker = DocumentPicker()
@State private var urlPick = ""
var body: some View {
HStack {
Text(urlPicked())
.padding()
.overlay(
RoundedRectangle(cornerRadius: 10)
.stroke(Color.white, lineWidth: 1)
)
TextField("", text: $urlPick)
.textFieldStyle(RoundedBorderTextFieldStyle())
.font(.system(size: 10))
.disabled(true)
Spacer()
Button(action: {
#if targetEnvironment(macCatalyst)
let viewController = UIApplication.shared.windows[0].rootViewController!
viewController.present(self.picker.viewController, animated: true)
self.picker.objectWillChange.send()
#endif
print("Hai premuto il pulsante per determinare il path della GeoFolder")
}) {
Image(systemName: "square.and.arrow.up")
}
}
.padding()
}
private func urlPicked() -> String {
var urlP = ""
if picker.urlsPicked.count > 0 {
urlP = picker.urlsPicked[0].path
urlPick = picker.urlsPicked[0].path
}
return urlP
}
}
如果我 运行 上面的代码我在 text
中得到了选择的正确路径,而在 textfield
中什么都没有并且我在 urlPick = picker.urlsPicked[0].path
中也有错误:Modifying state during view update, this will cause undefined behavior.
我如何修改代码以显示也在 textfield
?
have the error in urlPick = picker.urlsPicked[0].path: Modifying state during view update, this will cause undefined behavior. How can I modify the code to show the correct path chosen also in textfield?
尝试以下方法
if picker.urlsPicked.count > 0 {
urlP = picker.urlsPicked[0].path
DispatchQueue.main.async {
urlPick = picker.urlsPicked[0].path
}
}
任何想要创建具有只读权限的 MacOS 文档选择器的人,请使用以下解决方案:
import Foundation
import UIKit
extension ViewController: UIDocumentBrowserViewControllerDelegate, UIDocumentPickerDelegate {
@objc func presentDocumentPicker() {
if operatingSystem == .macintosh {
let documentPicker = UIDocumentBrowserViewController(forOpening: [.pdf])
documentPicker.delegate = self
documentPicker.allowsDocumentCreation = false
documentPicker.allowsPickingMultipleItems = false
// Present the document picker.
present(documentPicker, animated: true, completion: nil)
} else {
let documentsPicker = UIDocumentPickerViewController(forOpeningContentTypes: [.pdf])
documentsPicker.delegate = self
documentsPicker.allowsMultipleSelection = false
documentsPicker.modalPresentationStyle = .fullScreen
self.present(documentsPicker, animated: true, completion: nil)
}
}
func documentBrowser(_ controller: UIDocumentBrowserViewController, didPickDocumentsAt documentURLs: [URL]) {
guard let url = documentURLs.first, url.startAccessingSecurityScopedResource() else { return }
defer {
DispatchQueue.main.async {
url.stopAccessingSecurityScopedResource()
}
}
debugPrint("[DocumentPicker] Selected Item with URL : ", url)
controller.dismiss(animated: true)
}
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let url = urls.first, url.startAccessingSecurityScopedResource() else { return }
defer {
DispatchQueue.main.async {
url.stopAccessingSecurityScopedResource()
}
}
debugPrint("[DocumentPicker] Selected Item with URL : ", url)
controller.dismiss(animated: true)
}
public func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
controller.dismiss(animated: true)
}
}
请注意,如果权利是可读写的(即您还允许用户将文件保存到计算机)- 那么您可以简单地使用 UIDocumentPicker(我的代码段中的非 .macintosh 示例).