有没有办法从iCloud Drive中选择与UIImagePickerController()
类似的文件?
答案 0 :(得分:18)
您可以通过以下方式呈现控制器:
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)
在你的委托中实现方法:
func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL)
请注意,您无需设置iCloud权利即可使用UIDocumentPickerViewController
。 Apple提供了演示如何使用此控制器的示例代码here
答案 1 :(得分:3)
Swift 4.X
您需要在XCode功能中启用iCloud
权利。此外,您必须在Apple的开发者帐户中启用应用包中的iCloud
。完成此操作后,您可以通过以下方式显示文档选择器控制器:
使用UIDocumentPickerDelegate
方法
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)
}
}
为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)
}
这对我来说很好。希望它也能帮到你。
快乐编码:)
答案 2 :(得分:1)
Swift 5,iOS 13
Jhonattan和Ashu的答案肯定在核心功能的正确轨道上,多文档选择,错误结果和不建议使用的文档选择器API存在很多问题。
下面的代码显示了一个常见用例的现代化开始版本:选择一个外部iCloud文档以导入到应用程序中并对其进行处理。
请注意,您必须将应用程序的功能设置为使用iCloud文档,并在应用程序的.plist中设置普适容器...例如: 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)
}
}
}
答案 3 :(得分:1)
iCloudUrl.startAccessingSecurityScopedResource() //现在对我来说是正确的,
但是以下代码给出了错误:
尝试FileManager.default.createDirectory(atPath:iCloudUrl,withIntermediateDirectories:true,属性:nil)
“您无法保存文件“ xyz”,因为该卷是只读的。”
这实际上有效:
尝试FileManager.default.createDirectory(at:iCloudUrl,withIntermediateDirectories:true,属性:nil)
这是有道理的,因为URL可能带有它的安全访问权限,但是这种小疏忽使我感到困扰了半天……
答案 4 :(得分:0)
当用户选择应用程序沙箱外的目标时,文档选择器会调用委托的documentPicker:didPickDocumentAtURL:方法。系统会将文档副本保存到指定目标。文档选择器提供副本的URL以指示成功;但是,您的应用无法访问此网址引用的文件。 Link
此代码适用于我:
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)
}
答案 5 :(得分:0)
这在 iOS 14 中再次改变了!!
JSON的工作示例:
<?xml version="1.0" encoding="utf-8"?>
<selector xmlns:android="http://schemas.android.com/apk/res/android">
<item
android:color="@color/colorActive"
android:state_selected="true"
android:state_checked="true"/>
<item
android:color="@color/colorInactive"/>
</selector>