我想在我的 iOS 应用程序中选择任何类型的文件(.pdf、.docs、.xlsx、.jpeg、.txt、.rtf、等)。单击 Upload 按钮时,我希望我的应用程序打开一个目录并选择文件 (DocumentsPicker
)
@IBAction pickDocument(sender: UIButton) {
//Open Document Picker
}
有什么方法可以在 Swift 中做到这一点吗?
iOS 17 略有更新:
仅添加...
import UIKit // nothing else
class Job: UIViewController, UIDocumentPickerDelegate {
// delete "UIDocumentMenuDelegate"
然后...
@IBAction func tapSendFile() {
let pdfs = UTType.types(tag: "pdf",
tagClass: UTTagClass.filenameExtension, conformingTo: nil)
let txts = UTType.types(tag: "txt",
tagClass: UTTagClass.filenameExtension, conformingTo: nil)
// as many of those as you wish, then:
let doxy = UIDocumentPickerViewController(
forOpeningContentTypes: pdfs + txts)
doxy.delegate = self
self.present(doxy, animated: true, completion: nil)
}
最新语法:
func documentPicker(_ controller: UIDocumentPickerViewController,
didPickDocumentsAt urls: [URL]) {
print("IT WORKED")
}
iOS 14 更新:您不需要任何功能。只需创建一个具有适当类型的 UIDocumentPickerViewController
,实现委托,就完成了。
import UIKit
import MobileCoreServices
import UniformTypeIdentifiers
func selectFiles() {
let types = UTType.types(tag: "json",
tagClass: UTTagClass.filenameExtension,
conformingTo: nil)
let documentPickerController = UIDocumentPickerViewController(
forOpeningContentTypes: types)
documentPickerController.delegate = self
self.present(documentPickerController, animated: true, completion: nil)
}
iCloud
和
Key-Sharing
。在您的类中导入
MobileCoreServices
,然后在您的
UIViewController
中扩展以下三个类:
UIDocumentMenuDelegate,UIDocumentPickerDelegate,UINavigationControllerDelegate
实现以下功能:
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
guard let myURL = urls.first else {
return
}
print("import result : \(myURL)")
}
public func documentMenu(_ documentMenu:UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
present(documentPicker, animated: true, completion: nil)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
print("view was cancelled")
dismiss(animated: true, completion: nil)
}
你如何称呼这一切?将以下代码添加到您的点击函数中:
func clickFunction(){
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
单击您的按钮。将弹出以下菜单..以 Dropbox 为例。单击任何项目后。您将被重定向回您的应用程序,并且 URL 将记录在您的终端中。
根据您的需要操作文档类型。在我的应用程序中,用户仅允许使用 Pdf。所以,适合自己吧。
kUTTypePDF
kUTTypePNG
kUTTypeJPEG
...如果您想自定义自己的菜单栏。添加以下代码并在处理程序中自定义您自己的函数
importMenu.addOption(withTitle: "Create New Document", image: nil, order: .first, handler: { print("New Doc Requested") })
享受它。
UIDocumentPickerViewController
从“文件”应用程序或 iCloud Drive 获取文件。
Key-value storage
功能激活
iCloud Documents
和
iCloud
:
import MobileCoreServices
// For iOS 14+
import UniformTypeIdentifiers
UIDocumentPickerDelegate
实现以下方法:
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
// you get from the urls parameter the urls from the files selected
}
UIDocumentPickerViewController
以显示文件选择器或 iCloud Drive:
// Use this code if your are developing prior iOS 14
let types: [String] = [kUTTypePDF as String]
let documentPicker = UIDocumentPickerViewController(documentTypes: types, in: .import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
// For iOS 14+
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: [UTType.item], asCopy: false)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
UTType
types
中添加更多
NSArray
。要查看所有可用的类型,您可以查看UTType Docs 当文档选择器在 iOS 11 上打开并且您尝试选择 Google 云端硬盘中的文件时,该文件可能由于错误而被禁用:
UIDocumentMenuViewController
自 iOS11 起已弃用。当从模态视图控制器呈现时,我还发现它有问题。 这是使用选择器的直接方法:
import MobileCoreServices
private func attachDocument() {
let types = [kUTTypePDF, kUTTypeText, kUTTypeRTF, kUTTypeSpreadsheet]
let importMenu = UIDocumentPickerViewController(documentTypes: types as [String], in: .import)
if #available(iOS 11.0, *) {
importMenu.allowsMultipleSelection = true
}
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
present(importMenu, animated: true)
}
extension AViewController: UIDocumentPickerDelegate, UINavigationControllerDelegate {
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
viewModel.attachDocuments(at: urls)
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
controller.dismiss(animated: true, completion: nil)
}
}
像往常一样,不要忘记添加 iCloud 支持:
弃用
现在是 UIDocumentPickerViewController(forOpeningContentTypes:[UTType]
)ContentTypes 可以是以下任意项或以下项的组合:
UTType.image, UTType.text, UTType.plainText, UTType.utf8PlainText, UTType.utf16ExternalPlainText, UTType.utf16PlainText, UTType.delimitedText, UTType.commaSeparatedText, UTType.tabSeparatedText, UTType.utf8TabSeparatedText, UTType.rtf, UTType.pdf, UTType.webArchive, UTType.image, UTType.jpeg, UTType.tiff, UTType.gif, UTType.png, UTType.bmp, UTType.ico, UTType.rawImage, UTType.svg, UTType.livePhoto, UTType.movie, UTType.video, UTType.audio, UTType.quickTimeMovie, UTType.mpeg, UTType.mpeg2Video, UTType.mpeg2TransportStream, UTType.mp3, UTType.mpeg4Movie, UTType.mpeg4Audio, UTType.avi, UTType.aiff, UTType.wav, UTType.midi, UTType.archive, UTType.gzip, UTType.bz2, UTType.zip, UTType.appleArchive, UTType.spreadsheet, UTType.epub
这对我来说是这样的:
let supportedTypes = [myArrayFromAnyOfTheAbove]
func openDocument() {
let documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes, asCopy: true)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = false
documentPicker.shouldShowFileExtensions = true
present(documentPicker, animated: true, completion: nil)
}
let docsTypes = ["public.text",
"com.apple.iwork.pages.pages",
"public.data",
"kUTTypeItem",
"kUTTypeContent",
"kUTTypeCompositeContent",
"kUTTypeData",
"public.database",
"public.calendar-event",
"public.message",
"public.presentation",
"public.contact",
"public.archive",
"public.disk-image",
"public.plain-text",
"public.utf8-plain-text",
"public.utf16-external-plain-text",
"public.utf16-plain-text",
"com.apple.traditional-mac-plain-text",
"public.rtf",
"com.apple.ink.inktext",
"public.html",
"public.xml",
"public.source-code",
"public.c-source",
"public.objective-c-source",
"public.c-plus-plus-source",
"public.objective-c-plus-plus-source",
"public.c-header",
"public.c-plus-plus-header",
"com.sun.java-source",
"public.script",
"public.assembly-source",
"com.apple.rez-source",
"public.mig-source",
"com.apple.symbol-export",
"com.netscape.javascript-source",
"public.shell-script",
"public.csh-script",
"public.perl-script",
"public.python-script",
"public.ruby-script",
"public.php-script",
"com.sun.java-web-start",
"com.apple.applescript.text",
"com.apple.applescript.script",
"public.object-code",
"com.apple.mach-o-binary",
"com.apple.pef-binary",
"com.microsoft.windows-executable",
"com.microsoft.windows-dynamic-link-library",
"com.sun.java-class",
"com.sun.java-archive",
"com.apple.quartz-composer-composition",
"org.gnu.gnu-tar-archive",
"public.tar-archive",
"org.gnu.gnu-zip-archive",
"org.gnu.gnu-zip-tar-archive",
"com.apple.binhex-archive",
"com.apple.macbinary-archive",
"public.url",
"public.file-url",
"public.url-name",
"public.vcard",
"public.image",
"public.fax",
"public.jpeg",
"public.jpeg-2000",
"public.tiff",
"public.camera-raw-image",
"com.apple.pict",
"com.apple.macpaint-image",
"public.png",
"public.xbitmap-image",
"com.apple.quicktime-image",
"com.apple.icns",
"com.apple.txn.text-multimedia-data",
"public.audiovisual-content",
"public.movie",
"public.video",
"com.apple.quicktime-movie",
"public.avi",
"public.mpeg",
"public.mpeg-4",
"public.3gpp",
"public.3gpp2",
"public.audio",
"public.mp3",
"public.mpeg-4-audio",
"com.apple.protected-mpeg-4-audio",
"public.ulaw-audio",
"public.aifc-audio",
"public.aiff-audio",
"com.apple.coreaudio-format",
"public.directory",
"public.folder",
"public.volume",
"com.apple.package",
"com.apple.bundle",
"public.executable",
"com.apple.application",
"com.apple.application-bundle",
"com.apple.application-file",
"com.apple.deprecated-application-file",
"com.apple.plugin",
"com.apple.metadata-importer",
"com.apple.dashboard-widget",
"public.cpio-archive",
"com.pkware.zip-archive",
"com.apple.webarchive",
"com.apple.framework",
"com.apple.rtfd",
"com.apple.flat-rtfd",
"com.apple.resolvable",
"public.symlink",
"com.apple.mount-point",
"com.apple.alias-record",
"com.apple.alias-file",
"public.font",
"public.truetype-font",
"com.adobe.postscript-font",
"com.apple.truetype-datafork-suitcase-font",
"public.opentype-font",
"public.truetype-ttf-font",
"public.truetype-collection-font",
"com.apple.font-suitcase",
"com.adobe.postscript-lwfn-font",
"com.adobe.postscript-pfb-font",
"com.adobe.postscript.pfa-font",
"com.apple.colorsync-profile",
"public.filename-extension",
"public.mime-type",
"com.apple.ostype",
"com.apple.nspboard-type",
"com.adobe.pdf",
"com.adobe.postscript",
"com.adobe.encapsulated-postscript",
"com.adobe.photoshop-image",
"com.adobe.illustrator.ai-image",
"com.compuserve.gif",
"com.microsoft.bmp",
"com.microsoft.ico",
"com.microsoft.word.doc",
"com.microsoft.excel.xls",
"com.microsoft.powerpoint.ppt",
"com.microsoft.waveform-audio",
"com.microsoft.advanced-systems-format",
"com.microsoft.windows-media-wm",
"com.microsoft.windows-media-wmv",
"com.microsoft.windows-media-wmp",
"com.microsoft.windows-media-wma",
"com.microsoft.advanced-stream-redirector",
"com.microsoft.windows-media-wmx",
"com.microsoft.windows-media-wvx",
"com.microsoft.windows-media-wax",
"com.apple.keynote.key",
"com.apple.keynote.kth",
"com.truevision.tga-image",
"com.sgi.sgi-image",
"com.ilm.openexr-image",
"com.kodak.flashpix.image",
"com.j2.jfx-fax",
"com.js.efx-fax",
"com.digidesign.sd2-audio",
"com.real.realmedia",
"com.real.realaudio",
"com.real.smil",
"com.allume.stuffit-archive",
"org.openxmlformats.wordprocessingml.document",
"com.microsoft.powerpoint.ppt",
"org.openxmlformats.presentationml.presentation",
"com.microsoft.excel.xls",
"org.openxmlformats.spreadsheetml.sheet",
]
let documentPicker = UIDocumentPickerViewController(documentTypes: Utils.docsTypes, in: .import)
documentPicker.delegate = self
documentPicker.allowsMultipleSelection = true
present(documentPicker, animated: true, completion: nil)
let types: [String] = [
kUTTypeJPEG as String,
kUTTypePNG as String,
"com.microsoft.word.doc",
"org.openxmlformats.wordprocessingml.document",
kUTTypeRTF as String,
"com.microsoft.powerpoint.ppt",
"org.openxmlformats.presentationml.presentation",
kUTTypePlainText as String,
"com.microsoft.excel.xls",
"org.openxmlformats.spreadsheetml.sheet",
kUTTypePDF as String,
kUTTypeMP3 as String
]
let documentPicker = UIDocumentPickerViewController(documentTypes: types, in: .import)
documentPicker.delegate = self
documentPicker.modalPresentationStyle = .formSheet
self.present(documentPicker, animated: true, completion: nil)
我发现有两个地方对于整理此列表很有用:
https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html
https://escapetech.eu/manuals/qdrop/uti.html
希望对某人有帮助!
感谢这篇博文:
https://capps.tech/blog/read-files-with-documentpicker-in-swiftui
我只是在这里发布代码,以防博客文章消失,因此它被保留。(我稍微调整了代码以复制所选的证书文件并将数据写入Library文件夹;在博客中,它复制文本文件的内容。)
import SwiftUI
struct ContentView: View {
@State var fileContent:Data = Data()
@State var showDocumentPicker = false
var body: some View {
Button() {
showDocumentPicker = true
} label: {
Text("click me to show file browser")
}
.sheet(isPresented: self.$showDocumentPicker) {
DocumentPicker(fileContent: $fileContent)
}
}
}
struct DocumentPicker: UIViewControllerRepresentable {
@Binding var fileContent: Data
func makeCoordinator() -> DocumentPickerCoordinator {
return DocumentPickerCoordinator(fileContent: $fileContent)
}
func makeUIViewController(context:
UIViewControllerRepresentableContext<DocumentPicker>) ->
UIDocumentPickerViewController {
//The file types like ".pkcs12" are listed here:
//https://developer.apple.com/documentation/uniformtypeidentifiers/system_declared_uniform_type_identifiers?changes=latest_minor
let controller: UIDocumentPickerViewController = UIDocumentPickerViewController(forOpeningContentTypes: [.pkcs12], asCopy: true)
controller.delegate = context.coordinator
return controller
}
func updateUIViewController(_ uiViewController: UIDocumentPickerViewController, context: UIViewControllerRepresentableContext<DocumentPicker>) {
print("update")
}
} //struct
class DocumentPickerCoordinator: NSObject, UIDocumentPickerDelegate, UINavigationControllerDelegate {
@Binding var fileContent: Data
init(fileContent: Binding<Data>) {
_fileContent = fileContent
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
let fileURL = urls[0]
let certData = try! Data(contentsOf: fileURL)
if let documentsPathURL = FileManager.default.urls(for: .libraryDirectory, in: .userDomainMask).first {
let certURL = documentsPathURL.appendingPathComponent("certFile.pfx")
try? certData.write(to: certURL)
}
}
}
func openiCloudDocuments(){
let importMenu = UIDocumentPickerViewController(documentTypes: [String("public.data")], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
self.present(importMenu, animated: true, completion: nil)
}
NSURLSession
来实现您所描述的内容。您必须将显示的目标目录限制为应用程序的文档目录。应用程序没有对文件系统的完全访问权限。