How to access files in iCloud Drive from within my iOS app? - ios
Is there a way to choose file from iCloud Drive similar way to UIImagePickerController()?
You can present controller the following way:
import MobileCoreServices
let documentPickerController = UIDocumentPickerViewController(documentTypes: [String(kUTTypePDF), String(kUTTypeImage), String(kUTTypeMovie), String(kUTTypeVideo), String(kUTTypePlainText), String(kUTTypeMP3)], inMode: .Import)
documentPickerController.delegate = self
presentViewController(documentPickerController, animated: true, completion: nil)
In your delegate implement the method:
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL)
Note that you don't need to set up iCloud Entitlement to use UIDocumentPickerViewController. Apple provides sample code that demonstrates how to use this controller here
Swift 5, iOS 13
Jhonattan's and Ashu's answers are definitely on the right track for the core functionality, there are a number of issues with multiple-document-selection, error outcomes and deprecated document picker API.
The code below shows a modern start-to-finish version of a common use case: pick an external iCloud document to import into app and do something with it.
Note that you have to have your app's Capabilities set up to use iCloud documents and have a ubiquity container set up in your app's .plist... See for example:
Swift write/save/move a document file to iCloud drive
class ViewController: UIViewController {
#IBAction func askForDocument(_ sender: Any) {
if FileManager.default.url(forUbiquityContainerIdentifier: nil) != nil {
let iOSPickerUI = UIDocumentPickerViewController(documentTypes: ["public.text"], in: .import)
iOSPickerUI.delegate = self
iOSPickerUI.modalPresentationStyle = .formSheet
if let popoverPresentationController = iOSPickerUI.popoverPresentationController {
popoverPresentationController.sourceView = sender as? UIView
}
self.present(iOSPickerUI, animated: true, completion: nil)
}
}
func processImportedFileAt(fileURL: URL) {
// ...
}
}
extension ViewController: UIDocumentPickerDelegate, UINavigationControllerDelegate {
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
dismiss(animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
if controller.allowsMultipleSelection {
print("WARNING: controller allows multiple file selection, but coordinate-read code here assumes only one file chosen")
// If this is intentional, you need to modify the code below to do coordinator.coordinate
// on MULTIPLE items, not just the first one
if urls.count > 0 { print("Ignoring all but the first chosen file") }
}
let firstFileURL = urls[0]
let isSecuredURL = (firstFileURL.startAccessingSecurityScopedResource() == true)
print("UIDocumentPickerViewController gave url = \(firstFileURL)")
// Status monitoring for the coordinate block's outcome
var blockSuccess = false
var outputFileURL: URL? = nil
// Execute (synchronously, inline) a block of code that will copy the chosen file
// using iOS-coordinated read to cooperate on access to a file we do not own:
let coordinator = NSFileCoordinator()
var error: NSError? = nil
coordinator.coordinate(readingItemAt: firstFileURL, options: [], error: &error) { (externalFileURL) -> Void in
// WARNING: use 'externalFileURL in this block, NOT 'firstFileURL' even though they are usually the same.
// They can be different depending on coordinator .options [] specified!
// Create file URL to temp copy of file we will create:
var tempURL = URL(fileURLWithPath: NSTemporaryDirectory())
tempURL.appendPathComponent(externalFileURL.lastPathComponent)
print("Will attempt to copy file to tempURL = \(tempURL)")
// Attempt copy
do {
// If file with same name exists remove it (replace file with new one)
if FileManager.default.fileExists(atPath: tempURL.path) {
print("Deleting existing file at: \(tempURL.path) ")
try FileManager.default.removeItem(atPath: tempURL.path)
}
// Move file from app_id-Inbox to tmp/filename
print("Attempting move file to: \(tempURL.path) ")
try FileManager.default.moveItem(atPath: externalFileURL.path, toPath: tempURL.path)
blockSuccess = true
outputFileURL = tempURL
}
catch {
print("File operation error: " + error.localizedDescription)
blockSuccess = false
}
}
navigationController?.dismiss(animated: true, completion: nil)
if error != nil {
print("NSFileCoordinator() generated error while preparing, and block was never executed")
return
}
if !blockSuccess {
print("Block executed but an error was encountered while performing file operations")
return
}
print("Output URL : \(String(describing: outputFileURL))")
if (isSecuredURL) {
firstFileURL.stopAccessingSecurityScopedResource()
}
if let out = outputFileURL {
processImportedFileAt(fileURL: out)
}
}
}
The document picker calls the delegate’s documentPicker:didPickDocumentAtURL: method when the user selects a destination outside your app’s sandbox. The system saves a copy of your document to the specified destination. The document picker provides the copy’s URL to indicate success; however, your app does not have access to the file referred to by this URL. Link
This code work for me:
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) {
let url = urls[0]
let isSecuredURL = url.startAccessingSecurityScopedResource() == true
let coordinator = NSFileCoordinator()
var error: NSError? = nil
coordinator.coordinate(readingItemAt: url, options: [], error: &error) { (url) -> Void in
_ = urls.compactMap { (url: URL) -> URL? in
// Create file URL to temporary folder
var tempURL = URL(fileURLWithPath: NSTemporaryDirectory())
// Apend filename (name+extension) to URL
tempURL.appendPathComponent(url.lastPathComponent)
do {
// If file with same name exists remove it (replace file with new one)
if FileManager.default.fileExists(atPath: tempURL.path) {
try FileManager.default.removeItem(atPath: tempURL.path)
}
// Move file from app_id-Inbox to tmp/filename
try FileManager.default.moveItem(atPath: url.path, toPath: tempURL.path)
YourFunction(tempURL)
return tempURL
} catch {
print(error.localizedDescription)
return nil
}
}
}
if (isSecuredURL) {
url.stopAccessingSecurityScopedResource()
}
navigationController?.dismiss(animated: true, completion: nil)
}
This changed once again in iOS 14!!
Working example for JSON:
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)
}
Swift 4.X
You need to enable iCloud entitlements in XCode Capabilities. Also you have to turn on iCloud in you app bundle in developer account of Apple. Once you do this, you are able to present document picker controller by following way:
Use UIDocumentPickerDelegate methods
extension YourViewController : UIDocumentMenuDelegate, UIDocumentPickerDelegate,UINavigationControllerDelegate {
func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
self.present(documentPicker, animated: true, completion: nil)
}
func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) {
print("url = \(url)")
}
func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) {
dismiss(animated: true, completion: nil)
}
}
Add below code for Button Action
#IBAction func didPressAttachment(_ sender: UIButton) {
let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
importMenu.delegate = self
importMenu.modalPresentationStyle = .formSheet
if let popoverPresentationController = importMenu.popoverPresentationController {
popoverPresentationController.sourceView = sender
// popoverPresentationController.sourceRect = sender.bounds
}
self.present(importMenu, animated: true, completion: nil)
}
iCloudUrl.startAccessingSecurityScopedResource()
// is returning true for me at this point,
However the following code gave the error:
try FileManager.default.createDirectory(atPath: iCloudUrl, withIntermediateDirectories: true, attributes: nil)
"You can’t save the file “xyz” because the volume is read only."
This actually works :
try FileManager.default.createDirectory(at: iCloudUrl, withIntermediateDirectories: true, attributes: nil)
Which makes sense because the URL probably is carrying around it’s security access, but this little oversight stumped me for half a day…
For my swiftUI users: It's quite easy.
struct HomeView: View {
#State private var showActionSheet = false
var body: some View {
Button("Press") {
showActionSheet = true
}
.fileImporter(isPresented: $showActionSheet, allowedContentTypes: [.data]) { (res) in
print("!!!\(res)")
}
}
}
I use
try FileManager.default.copyItem(at: url, to: destinationUrl)
instead of moveItem. Otherwise, the files are removed from iCloud Drive, which is not what I want.
Related
Check condition for a zip file in UIDocumentPickerViewController
This is my code for calling UIDocumentPickerViewController to choose the files for my firmware update which have to be .zip only. When I press on "Select" button, the Document Picker View shows up: #IBAction func selectButtonAction(_ sender: UIButton) { if sender.title(for: .normal) == "Select"{ if let controller = (UIApplication.shared.delegate as? AppDelegate)?.currentViewController { let importMenu = UIDocumentPickerViewController(documentTypes: [String(kUTTypeArchive)], in: .open ) importMenu.delegate = self importMenu.modalPresentationStyle = .formSheet controller.present(importMenu, animated: true, completion: nil) } } else { changeDFUItemsDesign(isFileURLNil: true) } } Right now it's possible to open the files in .docx format, but I need to only let the user pick one format - a zip file. I cannot present what I have done so far because I am not able to find a solution. Is there a way to make a check for a zip file or just forbid selecting other formats? Thank you!
Intialize the DocumentPicker with the list of supported types. let zip = ["com.pkware.zip-archive"] let importMenu = UIDocumentPickerViewController(documentTypes: zip, in: .import) Here's a list of supported UTIs
In my view's extension I use the UIDocumentPickerDelegate and in the function I check if my file's last component is zip: func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { if let fileURL = urls.first, fileURL.pathExtension == "zip" { self._fileURL = fileURL self.fileNameLabel.text = _fileURL?.lastPathComponent } else { _fileURL = nil fileNameLabel.text = "Select file" } }
WKWebview not rendering .doc file but renders pdf/png/jpeg?
When trying to load a different file type (eg. PDF, PNG, JPEG), it works perfectly. Also tried loading the .doc data into a UIWebview and it also works fine. I am getting the data from a server using JSON encoded to Base64. let webview = WKWebView() webview.load(data, mimeType: "application/msword", characterEncodingName: "UTF-8", baseURL: NSURL() as URL) Has anyone faced this issue as well? The file should not save locally. It is the condition.
You need to use Quicklook for this, it is native feature of iOS:- import Foundation import UIKit import QuickLook class ClassQuickLookFilePreviewHandler { static let shared = ClassQuickLookFilePreviewHandler() var url: URL? var tempURL: URL? func previewFile(vc: UIViewController, url: URL, fileName: String) { let previewController = QLPreviewController() self.url = url previewController.dataSource = self previewController.view.tintColor = UIColor(hexString: "#ff3366") tempURL = FileManager.default.temporaryDirectory.appendingPathComponent(fileName) previewController.currentPreviewItemIndex = 0 URLSession.shared.dataTask(with: url) { data, _, error in guard let data = data, error == nil else { // in case of failure to download your data you need to present alert to the user and update the UI from the main thread DispatchQueue.main.async { UIApplication.shared.isNetworkActivityIndicatorVisible = false let alert = UIAlertController(title: "Alert", message: error?.localizedDescription ?? "Failed to download the pdf!!!", preferredStyle: .alert) alert.addAction(UIAlertAction(title: "OK", style: .default)) vc.present(alert, animated: true) } return } // write the downloaded data to a temporary folder or to the document directory if you want to keep the pdf for later usage do { try data.write(to: self.tempURL!, options: .atomic) // atomic option overwrites it if needed // you neeed to check if the downloaded data is a valid pdf // and present your controller from the main thread DispatchQueue.main.async { UIApplication.shared.isNetworkActivityIndicatorVisible = false vc.present(previewController, animated: true) } } catch { print(error) return } }.resume() UIApplication.shared.isNetworkActivityIndicatorVisible = true } } extension ClassQuickLookFilePreviewHandler: QLPreviewControllerDataSource { func numberOfPreviewItems(in controller: QLPreviewController) -> Int { return 1 } func previewController(_ controller: QLPreviewController, previewItemAt index: Int) -> QLPreviewItem { return tempURL! as QLPreviewItem } } Usage:- ClassQuickLookFilePreviewHandler.shared.previewFile(vc: self, url: URL(string: ?*documentURL)!, fileName: ?*documentFileName) Hope it helps :)
By UIImagePickerController we can access and upload images. How to access and upload documents from iphone?
I'm developing a loan related app where user upload his documents like pay-slips, it-returns, etc. For that I should show the user all the documents he/she having in his/her iPhone. How to show a picker for documents?
UIDocumentPickerViewController is what you are looking for. You init one with a list of document types you want to be able to pick, and a mode, which is usually .open to get access to a file in a cloud provider directly. You can also use .import which will copy the file to your container instead of giving you access to the file in the cloud provider's container directly, if the goal is just to upload it (you can remove the copy after uploading). Once you have created your picker, you present it, and implement the delegate method didPickDocumentsAt to retrieve the list of files chosen by the user. Check out the Particles sample code and this years WWDC session « Managing Documents in your iOS Apps »
just call openDocumentPicker method when you want to upload document in your application.. import MobileCoreServices func openDocumentPicker() { let importMenu = UIDocumentMenuViewController(documentTypes: [kUTTypePDF as String], in: .import) importMenu.delegate = self self.present(importMenu, animated: true, completion: nil) } create your viewcontroller extension extension ViewController: UIDocumentMenuDelegate { func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) { documentPicker.delegate = self present(documentPicker, animated: true, completion: nil) } func documentMenuWasCancelled(_ documentMenu: UIDocumentMenuViewController) { print("we cancelled") dismiss(animated: true, completion: nil) } } extension ViewController: UIDocumentPickerDelegate { internal func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { do { let fileAttributes = try FileManager.default.attributesOfItem(atPath: url.path) let fileSizeNumber = fileAttributes[FileAttributeKey.size] as! NSNumber let fileSizea = fileSizeNumber.doubleValue let fileSize = fileSizea/1000000.0 if fileSize > 5.0 { appDelegate.displayAlert(Title: "", Message: "Selected File are too big,Please select file less than 5.0 mb") } else { let documentData = try Data(contentsOf: url, options: .dataReadingMapped) } } catch let error { print(error.localizedDescription) } } } above this code only you can access pdf if you want to access anpther document than just use this code /* let pdf = String(kUTTypePDF) let spreadsheet = String(kUTTypeSpreadsheet) let movie = String(kUTTypeMovie) let aviMovie = String(kUTTypeAVIMovie) let docs = String(kUTTypeCompositeContent) let img = String(kUTTypeImage) let png = String(kUTTypePNG) let jpeg = String(kUTTypeJPEG) let txt = String(kUTTypeText) let zip = String(kUTTypeZipArchive) let msg1 = String(kUTTypeEmailMessage) let msg2 = String(kUTTypeMessage) let types = [pdf, spreadsheet, movie, aviMovie, img, png, jpeg, txt, docs, zip, msg1, msg2] */
iOS 11 or later let importMenu = UIDocumentPickerViewController.init(documentTypes: ["public.item"], in: UIDocumentPickerMode.import) self.present(importMenu, animated: true) { } Please Refer the following link for more description https://www.techotopia.com/index.php/An_iOS_Document_Browser_Tutorial iOS 10 or earlier You can write the below function when your document picker opens. it will work for all the file types which you want to upload. func openDocumentPicker() { let importMenu = UIDocumentMenuViewController(documentTypes: ["public.item"], in: .import) importMenu.delegate = self importMenu.modalPresentationStyle = .formSheet self.present(importMenu, animated: true, completion: nil) }
UIDocumentMenuViewController blank Options
I have a problem with iCloud file import I'm getting empty options after I choose the place to import from (iCloud, google drive, dropbox ... etc) I have data on iCloud drive and the entitlements are right So what is wrong with this code or is there anything about the settings may cause this problem? here is the code #IBAction func selectionButtonAction(_ sender: Any) { let types = [kUTTypePDF as String ,kUTTypePNG as String, kUTTypeImage as String,kUTTypeJPEG as String] UINavigationBar.appearance().isTranslucent = true let documentMenu = UIDocumentMenuViewController(documentTypes: types, in: .import) documentMenu.delegate = self self.viewController?.present(documentMenu, animated: true, completion: nil) } func documentMenu(_ documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) { documentMenu.delegate = self self.viewController?.present(documentMenu, animated: true, completion: nil) } func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) { if controller.documentPickerMode == .import { // do staff } } Here is what I get When I run the app on iOS 10 When I Press choose File then after pressing on iCloud That's what I get if I run the app on iOS 9: I'm sure I have data there like here in the iCloud Drive application And the entitlement
I had the same problem, when trying to present a already used Instance of the UIDocumentMenuViewController. I was instantiating it lazily like this: lazy var documentMenuController: UIDocumentMenuViewController = { let controller = UIDocumentMenuViewController(documentTypes: ["com.adobe.pdf"], in: .import) controller.delegate = self return controller }() Which produced this error every time except the first time. So I changed the code to this: var documentMenuController: UIDocumentMenuViewController { let controller = UIDocumentMenuViewController(documentTypes: ["com.adobe.pdf"], in: .import) controller.delegate = self return controller } To obtain a fresh instance on every access of the property.
Implement Document Picker in swift (iOS)
I want to pick a file of any type(.pdf, .docs, .xlsx, .jpeg, .txt, .rtf, etc) functionality in my iOS app. On clicking on Upload button, I want my app to open a directory and select files(DocumentsPicker) #IBAction pickDocument(sender: UIButton) { //Open Document Picker } Any approach to do so in Swift?
Update for iOS 14: You do not need any capabilities. Just create a UIDocumentPickerViewController with the appropriate types, implement the delegate, and you are done. More info in this answer. Code from there: 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) } From your project's capabilities, enable both the iCloud and the Key-Sharing. Import MobileCoreServices in your class and then extend the following three classes inside your UIViewController: UIDocumentMenuDelegate,UIDocumentPickerDelegate,UINavigationControllerDelegate Implement the following functions: 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) } How do you call all of this? Add the following bit of code to your click function: func clickFunction(){ let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import) importMenu.delegate = self importMenu.modalPresentationStyle = .formSheet self.present(importMenu, animated: true, completion: nil) } Click your button. The following menu will pop up .. In the case of Dropbox. Upon clicking on any item. You will be redirected back to your app and the URL will be logged in your terminal. Manipulate the documentTypes to your need. In my app, Users permitted to Pdf only. So, suit yourself. kUTTypePDF kUTTypePNG kUTTypeJPEG ... Also if you feel like customizing your own menu bar. Add the following code and customize your own function inside the handler importMenu.addOption(withTitle: "Create New Document", image: nil, order: .first, handler: { print("New Doc Requested") }) Enjoy it.
You can use UIDocumentPickerViewController to get the files from the Files apps or iCloud Drive. Activate the Key-value storage and iCloud Documents from iCloud capability: Import the following framework on the view controller you want to open the document picker: import MobileCoreServices // For iOS 14+ import UniformTypeIdentifiers Implement the following method from UIDocumentPickerDelegate: func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentsAt urls: [URL]) { // you get from the urls parameter the urls from the files selected } Create an UIDocumentPickerViewController to display the File picker or 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) If you want the user can import more types of files to your app, you have to add more UTTypes to the types NSArray. To see all the types available, you can check the UTType Docs When the document picker opens on iOS 11 and you try to select a file inside the Google Drive, it is possible the file is disable due a bug: http://www.openradar.me/24187873
The UIDocumentMenuViewController is deprecated since iOS11. I also found it buggy when presented from a modal view controller. Here's a direct way of using the picker: 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) } } As usual don't forget to add iCloud support:
UIDocumentPickerViewController(documentTypes: [String], in: UIDocumentPickerMode) was deprecated in iOS 14.0 It is now UIDocumentPickerViewController(forOpeningContentTypes: [UTType]) ContentTypes being and array any or the combination of the following: 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 This is how it works for me: 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)
this will help you to implement download/upload functionality UIDocumentMenuViewController *importMenu = [[UIDocumentMenuViewController alloc] initWithDocumentTypes:#[#"public.item"] inMode:UIDocumentPickerModeImport | UIDocumentPickerModeExportToService]; For more read Apple Documentation
iCloud access all type of files # func openiCloudDocuments(){ let importMenu = UIDocumentPickerViewController(documentTypes: [String("public.data")], in: .import) importMenu.delegate = self importMenu.modalPresentationStyle = .formSheet self.present(importMenu, animated: true, completion: nil) }
Something I struggled with was how to specify some specific formats for the PickerView, such as .pptx & .xlsx files. Here's some code to create a PickerView with some commonly required types... 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) There are two places that I found useful in putting together this list: https://developer.apple.com/library/archive/documentation/Miscellaneous/Reference/UTIRef/Articles/System-DeclaredUniformTypeIdentifiers.html https://escapetech.eu/manuals/qdrop/uti.html Hope that helps somebody!
Here's a SwiftUI version of UIDocumentPickerViewController. Credit goes to this blog post: https://capps.tech/blog/read-files-with-documentpicker-in-swiftui I'm just posting the code here in case the blog post disappears so it's preserved. (I adjusted the code slightly to copy the selected certificate file and write the Data to the Library folder; in the blog, it copies the contents of a text file.) 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) } } }
You could implement what you describe using NSURLSession. You will have to limit the target directory you show to your app's documents directory. Apps do not have full access to the file system.