documentBrowser(_:didRequestDocumentCreationWithHandler:)
的文档说:“创建一个新文档并将其保存到临时位置。如果使用UIDocument
子类创建文档,则必须在调用{{}之前关闭它。 1}}阻止。“
所以我通过获取用户临时目录(importHandler
)的URL并附加名称和扩展名(获取类似“file:/// private / var / mobile / Containers /的路径)来创建文件URL数据/应用/ C1DE454D-EA1E-4166-B137-5B43185169D8 / TMP / Untitled.uti“)。但是当我调用FileManager.default.temporaryDirectory
传递此URL时,永远不会回调完成处理程序。我还尝试使用save(to:for:completionHandler:)
传递用户临时目录中的子目录 - 仍未调用完成处理程序。
我理解文档浏览器视图控制器由一个单独的进程管理,该进程有自己的读/写权限。除此之外,我很难理解问题所在。临时保存新文档的位置,以便文档浏览器进程可以移动它们?
更新:截至目前的测试版,我现在看到域url(for:in:appropriateFor:create:)
和代码NSFileProviderInternalErrorDomain
出现错误:“不允许读者访问该网址。”至少那是对发生的事情的确认......
答案 0 :(得分:10)
因此,首先,如果您使用的是自定义UTI,则必须正确设置。我看起来像这样......
-Dlogback.configurationFile
和
<key>CFBundleDocumentTypes</key>
<array>
<dict>
<key>CFBundleTypeIconFiles</key>
<array>
<string>icon-file-name</string> // Can be excluded, but keep the array
</array>
<key>CFBundleTypeName</key>
<string>Your Document Name</string>
<key>CFBundleTypeRole</key>
<string>Editor</string>
<key>LSHandlerRank</key>
<string>Owner</string>
<key>LSItemContentTypes</key>
<array>
<string>com.custom-uti</string>
</array>
</dict>
</array>
另外
<key>UTExportedTypeDeclarations</key>
<array>
<dict>
<key>UTTypeConformsTo</key>
<array>
<string>public.data</string> // My doc is saved as Data, not a file wrapper
</array>
<key>UTTypeDescription</key>
<string>Your Document Name</string>
<key>UTTypeIdentifier</key>
<string>com.custom-uti</string>
<key>UTTypeTagSpecification</key>
<dict>
<key>public.filename-extension</key>
<array>
<string>doc-extension</string>
</array>
</dict>
</dict>
</array>
我将<key>UISupportsDocumentBrowser</key>
<true/>
子类化为UIDocument
并添加以下方法来创建新的临时文档...
MyDocument
然后按如下方式初始化并显示DBVC:
static func create(completion: @escaping Result<MyDocument> -> Void) throws {
let targetURL = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("Untitled").appendingPathExtension("doc-extension")
coordinationQueue.async {
let document = MyDocument(fileURL: targetURL)
var error: NSError? = nil
NSFileCoordinator(filePresenter: nil).coordinate(writingItemAt: targetURL, error: &error) { url in
document.save(to: url, for: .forCreating) { success in
DispatchQueue.main.async {
if success {
completion(.success(document))
} else {
completion(.failure(MyDocumentError.unableToSaveDocument))
}
}
}
}
if let error = error {
DispatchQueue.main.async {
completion(.failure(error))
}
}
}
}
我的委托方法如下:
@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {
lazy var documentBrowser: UIDocumentBrowserViewController = {
let utiDecs = Bundle.main.object(forInfoDictionaryKey: kUTExportedTypeDeclarationsKey as String) as! [[String: Any]]
let uti = utiDecs.first?[kUTTypeIdentifierKey as String] as! String
let dbvc = UIDocumentBrowserViewController(forOpeningFilesWithContentTypes:[uti])
dbvc.delegate = self
return dbvc
}()
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool {
window = UIWindow(frame: UIScreen.main.bounds)
window?.rootViewController = documentBrowser
window?.makeKeyAndVisible()
return true
}
}
这就是它。让我知道你是如何上场的!
答案 1 :(得分:3)
我有同样的问题,但后来我意识到推荐的方法是简单地从Bundle中复制包/文件夹,如下所示:
func documentBrowser(_ controller: UIDocumentBrowserViewController, didRequestDocumentCreationWithHandler importHandler: @escaping (URL?, UIDocumentBrowserViewController.ImportMode) -> Void) {
if let url = Bundle.main.url(forResource: "Your Already Created Package", withExtension: "your-package-extension") {
importHandler(url, .copy)
} else {
importHandler(nil, .none)
}
}
为了澄清一下,这个包只是你创建的一个文件夹,并且已经填入Xcode。
如果您考虑这个问题,这种方法很有意义,原因如下:
Apple文件系统(AFS)。向AFS的转变意味着复制(几乎)是免费的。
权限。始终允许从Bundle复制,并且用户正在指定要复制到的位置。
新文档浏览器范例。由于我们正在使用新的UIDocumentBrowserViewController
范例(由于iOS11和新的文件应用程序),它甚至可以处理命名(例如Apple的页面)以及移动和排列文件。我们不必担心在哪个线程上运行。
因此。更简单,更容易,也可能更好。我想不出手动创建所有文件的原因(或使用临时文件夹等)。
答案 2 :(得分:1)
在设备上测试,而不是在模拟器中。我在设备上切换到测试的那一刻,一切都刚刚开始正常工作。 (注意:模拟器故障可能仅发生在像我这样的Sierra用户身上。)