我有一个基于文档的iOS应用程序与UIDocument子类.我需要能够移动它在文件系统上表示的文件.我考虑过用它移动它NSFileManager,但这会弄乱它UIDocument的fileURL财产.关于如何解决这个小难题的任何想法?
有没有办法检查 UIDocument(正在与 iCloud 同步)是否已使用 iCloud 在其他地方打开 - 除了等待发生冲突?
我有一个UIDocument基于应用程序,使用NSFileWrappers来存储数据.'master'文件包装器包含许多其他目录文件包装器,每个包装器代表文档的不同页面.
每当我在UIDocument保存(in writeContents:andAttributes:safelyToURL:forSaveOperation:error:)时对文档进行更改时,应用程序崩溃.这是堆栈跟踪:

很明显,我正在修改UIDocument在后台枚举的文件包装器的同一个实例.实际上,我检查了当返回数据模型的快照时contentsForType:error:,返回的子文件包装器指向与数据模型中当前驻留(和正在编辑)的对象相同的对象,而不是副本.
- (id)contentsForType:(NSString *)typeName error:(NSError *__autoreleasing *)outError
{
if (!_fileWrapper) {
[self setupEmptyDocument];
}
return [[NSFileWrapper alloc] initDirectoryWithFileWrappers:[_fileWrapper fileWrappers]];
}
Run Code Online (Sandbox Code Playgroud)
这是实施此方法的认可方法(根据WWDC 2012会议218 - 使用带有UIDocument的iCloud).
所以我想问题是:这种方法如何是线程安全的?
当主文件包装器fileWrappers本身是目录文件包装器时,情况是否有所不同?如果受制裁的方法是错误的,应该怎么做?
文档documentBrowser(_:didRequestDocumentCreationWithHandler:)说:"创建一个新文档并将其保存到临时位置.如果使用UIDocument子类创建文档,则必须在调用importHandler块之前将其关闭."
所以我通过获取用户临时目录(FileManager.default.temporaryDirectory)的URL 并附加名称和扩展名(获取类似"file:/// private/var/mobile/Containers/Data/Application/C1DE454D-EA1E-的路径)来创建文件URL 4166-B137-5B43185169D8/TMP/Untitled.uti").但是当我调用save(to:for:completionHandler:)传递此URL时,永远不会回调完成处理程序.我也尝试使用url(for:in:appropriateFor:create:)在用户的临时目录中传递一个子目录 - 仍然没有调用完成处理程序.
我理解文档浏览器视图控制器由一个单独的进程管理,该进程有自己的读/写权限.除此之外,我很难理解问题所在.临时保存新文档的位置,以便文档浏览器进程可以移动它们?
更新:截至目前的测试版,我现在看到一个错误的域NSFileProviderInternalErrorDomain和代码1被记录:"不允许读者访问该URL." 至少那是对发生的事情的确认......
我正在努力弄清楚如何UIDocument在iCloud文件夹中重命名子类的实例.我尝试使用新网址保存文档...
func renameDocument(to name: String) {
let targetURL = document.fileURL.deletingLastPathComponent().appendingPathComponent(name)
.appendingPathExtension("<extension>")
document.save(to: targetURL, for: .forCreating) { success in
guard success else {
// This always fails
return
}
// Success
}
}
Run Code Online (Sandbox Code Playgroud)
......但这失败了......
Error Domain=NSCocoaErrorDomain Code=513 "“<new-file-name>” couldn’t be moved because you don’t have permission to access “<folder>”."UserInfo={NSSourceFilePathErrorKey=/private/var/mobile/Containers/Data/Application/1A9ACC2B-81EF-4EC9-940E-1C129BDB1914/tmp/(A Document Being Saved By My App)/<new-file-name>, NSUserStringVariant=( Move ), NSDestinationFilePath=/private/var/mobile/Library/Mobile Documents/com~apple~CloudDocs/<folder>/<new-file-name>, NSFilePath=/private/var/mobile/Containers/Data/Application/1A9ACC2B-81EF-4EC9-940E-1C129BDB1914/tmp/(A Document Being Saved By My App)/<new-file-name>, NSUnderlyingError=0x1c4e54280 {Error Domain=NSPOSIXErrorDomain Code=1 "Operation not permitted"}}
......而且只是一个简单的举动......
func renameDocument(to name: …Run Code Online (Sandbox Code Playgroud) 某些具有自定义文件类型的 iOS 应用程序会在点击该类型的文件时自动启动(例如,如果在“文件”应用程序中点击页面文件,则会启动页面)。作为 UTI 所有者的 iOS 应用程序如何获得相同的行为?(特别是 UTI 符合com.apple.package)
我正在使用https://www.raywenderlich.com/133825/uiactivityviewcontroller-tutorial 中的示例 BeerTracking 应用程序。当在文件应用程序/邮件/笔记中点击从应用程序导出的文件时,会出现一个空的快速预览 UI,然后用户才能通过点击共享在应用程序中打开文件。
我正在处理UIDocument应用程序,我想在用户打开文档之前向用户展示文档的预览。当文档关闭时,我可以将该预览呈现为图像。但是我应该在哪里保存该图像?在另一个文件中?或者有没有指定的方法来做到这一点?
现在我在没有 iCloud 支持的情况下开发它。但我想有一个也适用于 iCloud 的解决方案。这UIDocument是一个UIManagedDocument. 但是将图像保存到数据库中会使它变得毫无意义。因为那时我必须打开文档才能获得预览。
你在这里推荐什么?在哪里放预览UIManagedDocument?
我有一个UIDocument名字叫“老”。我对其进行了一些更改,并希望以“ New”的名称重新保存它。“旧”的内容不应更改。这是我失败的尝试:
首先,将尚未保存的“旧”文档复制到“新”文件位置。将“旧”文档保存到“新”文件位置。从理论上讲,由于“旧”文档从未保存到文件系统中的URL,因此它仍应处于“旧”状态。“新”文件位置应将“旧”文件的最新更改,因为我们只是将“旧”文件保存到“新”文件位置。
NSFileManager *manager = [NSFileManager defaultManager];
NSURL *newFileLocation = [documentDirectoryURL URLByAppendingPathComponent:[NSString stringWithFormat:@"%@.%@", document.title, DOCUMENT_EXTENSION]];
NSURL *oldFileLocationCopy = document.fileURL.copy;
NSError *error;
BOOL copySuccess = [manager copyItemAtURL:oldFileLocationCopy toURL:newFileLocation error:&error];
if (! copySuccess)
{
NSLog(@"File not successfully copied.");
return;
}
[document saveToURL:newFileLocation forSaveOperation:UIDocumentSaveForOverwriting completionHandler:^(BOOL success)
{
if (success)
{
handler();
}
else
{
NSLog(@"New file rename not saved.");
}
}];
Run Code Online (Sandbox Code Playgroud)
该代码的结果只是一个简单的重命名操作。“旧”消失,“新”具有新保存的文档的内容。
我觉得这应该很容易,但是我还没有在SO上找到任何类似的问题。提前致谢!
当我尝试从 iCloud Drive 或 Dropbox 将文件导入到我的服务器时, startAccessingSecurityScopedResource()仅返回 false 设备,但在模拟器(Xcode 8、Swift 2.3、最低目标 8.0)中测试时返回 true。
这是我的代码:
{
func showCloudDriveAction(inputBar: NAChatInputBar) {
let documentmenuPicker = UIDocumentMenuViewController(documentTypes: ["public.data"], inMode: .Import)
documentmenuPicker.delegate = self
presentViewController?.presentViewController(documentmenuPicker, animated: true, completion: nil)
}
}
extension NAChatInputBarPresenter: UIDocumentPickerDelegate, UIDocumentMenuDelegate {
public func documentMenu(documentMenu: UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) {
documentPicker.delegate = self
self.presentViewController?.presentViewController(documentPicker, animated: true, completion: nil)
}
public func documentPicker(controller: UIDocumentPickerViewController, didPickDocumentAtURL url: NSURL) {
if url.startAccessingSecurityScopedResource() {
guard let path = url.path, data = NSData(contentsOfFile: path) else …Run Code Online (Sandbox Code Playgroud) 设置文档选择器,用户可以从“文件应用程序”中选择 PDF 文件,并将其保存到我的应用程序文档文件夹中以在应用程序中使用。
打开文档选择器,选择文件 - 但关闭后出现以下错误:
“[DocumentManager] 视图服务确实终止并出现错误:Error Domain=_UIViewServiceErrorDomain Code=1 “(null)”UserInfo={Termminate=disconnect method}”
UIViewController代码:
import UIKit
import CoreData
import PDFKit
import MobileCoreServices
import UniformTypeIdentifiers
class AddDocumentViewController: UIViewController, UIImagePickerControllerDelegate, UINavigationControllerDelegate, UIDocumentPickerDelegate {
@IBAction func chooseFile (_ sender: UIButton) {
fileTypeSelectionInput = fileTypeSelection.selectedSegmentIndex
var documentPicker: UIDocumentPickerViewController!
if #available(iOS 14, *) {
// iOS 14 & later
let supportedTypes: [UTType] = [UTType.pdf]
documentPicker = UIDocumentPickerViewController(forOpeningContentTypes: supportedTypes)
} else {
// iOS 13 or older code
let supportedTypes: [String] = [kUTTypeImage as String]
documentPicker = …Run Code Online (Sandbox Code Playgroud) uidocument ×10
ios ×7
icloud ×4
ios11 ×2
ios5 ×2
cocoa-touch ×1
copy ×1
filesystems ×1
iphone ×1
rename ×1
save ×1
swift ×1
uikit ×1
uti ×1