文件管理器有时在文档目录

时间:2017-12-12 19:14:03

标签: ios swift wkwebview

我以前曾问过这个问题,但不得不重新制定一切,以便更容易理解。

在我的项目中,我使用以下代码在名为documents directory的{​​{1}}内创建了一个子文件夹:

HTML

print语句打印以下内容:

  

文件目录为file:/// var / mobile / Containers / Data / Application / 103869C9-9D46-4595-A370-A93BCD75D495 / Documents / HTML

在我的应用内fileprivate func createFolderOnDocumentsDirectoryIfNotExists() { let folderName = "HTML" let fileManager = FileManager.default if let tDocumentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first { let filePath = tDocumentDirectory.appendingPathComponent("\(folderName)") if !fileManager.fileExists(atPath: filePath.path) { do { try fileManager.createDirectory(atPath: filePath.path, withIntermediateDirectories: true, attributes: nil) } catch { print("Couldn't create document directory") } } print("Document directory is \(filePath)") } } 我有一个Bundle文件供我在.css中使用HTML字符串。

由于WKWebView文件需要与.css位于同一文件夹中,我将HTML baseURL文件从.css复制到使用上述功能创建的目录中,使用以下代码:

Bundle

我知道我可以通过将fileprivate func copyCSSFileToHTMLFolder() { guard let cssURL = Bundle.main.url(forResource: "swiss", withExtension: "css") else { return } let fileManager = FileManager.default if let tDocumentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask).first { let fp = tDocumentDirectory.appendingPathComponent("HTML") if fileManager.fileExists(atPath: fp.path) { let fp2 = fp.appendingPathComponent(cssURL.lastPathComponent) do { try fileManager.copyItem(atPath: cssURL.path, toPath: fp2.path) } catch { print("\nFailed to copy css to HTML folder with error:", error) } } } } 设置为Bundle来在应用的HTML baseURL中使用这两者,但因为我需要在main.Bundle内呈现本地图片而不是网页链接的图片,我不得不将它们移动到子文件夹中,以便我以后将所需的图像复制到该子文件夹中,因为HTML是只读的而且不可写(我们无法保存图像)。 / p>

现在我有一个main.Bundle被推进ViewController;内部推送UINavigationController我有一个ViewController,会显示WKWebView

我还有一个HTML属性,一旦实例化,我使用以下函数将其转换为var markdownString: String? {}字符串:

HTML

使用以下代码声明我的func getHTML(str: String) -> String { /* the cssImport here points to the previously copied css file as they are on the same folder */ let cssImport = "<head><link rel=\"stylesheet\" type=\"text/css\" href=\"swiss.css\"></head>" let htmlString = try? Down(markdownString: str).toHTML() return cssImport + htmlString! }

WKWebView

每当我设置private lazy var webView: WKWebView = { // script to fit the content with the screen var scriptContent = "var meta = document.createElement('meta'); meta.setAttribute('name', 'viewport'); meta.setAttribute('content', 'width=device-width'); document.getElementsByTagName('head')[0].appendChild(meta);" let wkuscript = WKUserScript(source: scriptContent, injectionTime: WKUserScriptInjectionTime.atDocumentEnd, forMainFrameOnly: true) let wkucontroller = WKUserContentController() wkucontroller.addUserScript(wkuscript) let wkwebconfig = WKWebViewConfiguration() wkwebconfig.userContentController = wkucontroller let wv = WKWebView(frame: .zero, configuration: wkwebconfig) wv.frame.size.height = 1 return wv }() 时,我会将其转换为markdown String字符串,然后我实例化HTML,然后使用以下代码将其加载到我的HTML baseURL中:

webView

这是我的问题开始的地方。

public var markdownString: String? { didSet { guard let kPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first?.appendingPathComponent("HTML", isDirectory: true) else { return } guard let str = markdownString else { return } let html = getHTML(str: str) print("base url:", kPath) let fm = FileManager.default do { let items = try fm.contentsOfDirectory(atPath: kPath.path) print("items:", items) } catch { print("Error:", error) } webView.loadHTMLString(html, baseURL: kPath) } } 文件位于以下目录中:

  

文件:/// VAR /移动/容器/数据/应用/ 103869C9-9D46-4595-A370-A93BCD75D495 /文档/ HTML /

swiss.css指向以下路径:

  

文件:/// VAR /移动/容器/数据/应用/ 103869C9-9D46-4595-A370-A93BCD75D495 /文档/ HTML /

正如你所看到的,他们都指向同一条道路。

有时我的HTML baseURL会找到HTML文件,因为它会在swiss.css块中打印items,但有时却找不到该文件夹​​,{ {1}}触发do{}catch{}块中捕获的错误,打印以下内容:

  

错误:错误域= NSCocoaErrorDomain代码= 260“文件夹”HTML“不存在。” UserInfo = {NSFilePath = / var / mobile / Containers / Data / Application / 103869C9-9D46-4595-A370-A93BCD75D495 / Documents / HTML,NSUserStringVariant =(       夹   ),NSUnderlyingError = 0x1c044e5e0 {错误域= NSPOSIXErrorDomain代码= 2“没有这样的文件或目录”}}

这两种情况都发生在模拟器和真实设备上。

造成这个问题的原因是什么?为什么它有时会找到文件夹而有时却没有找到它,即使没有重新启动应用程序,这可能会重置try fm.contentsOfDirectory(atPath: kPath.path)路径,即使我没有强制使用路径,而是我将其取为你可以在上面看到。

我不明白这种行为。

更新

所以我认为直接阅读catch{}字符串可能会导致一些问题,所以我更改了documents directory声明。

在其中,我将转换后的markdown字符串(不是html字符串)写入同一路径中的文件,称为html

现在有人认为发生了不同的事情 - 当我第一次推送此视图时,它现在找到我的markdown: String?文件,index.html文件检测到它并按预期使用它;到目前为止一切顺利。

当我关闭此视图控制器时,弹出到父视图控制器(按后退按钮)然后尝试再次按下它,同样的错误(如前所述)提示:

  

无法将html写入错误文件:Error Domain = NSCocoaErrorDomain Code = 4“文件夹”index.html“不存在。” UserInfo = {NSURL = file:///var/mobile/Containers/Data/Application/C0639153-6BA7-40E7-82CF-25BA4CB4A943/Documents/HTML/index.html,NSUserStringVariant = Folder,NSUnderlyingError = 0x1c045d850 {Error Domain = NSPOSIXErrorDomain代码= 2“没有这样的文件或目录”}}

请注意,这里的一些路径与前一个路径不同,因为它是一个不同的启动而且它会发生变化,但这不是问题,因为我从不存储路径并强制写入它,我总是使用默认文件管理器提取,

更新的swiss.css声明如下:

html

不知何故,这让我更加困惑。

为什么它适用于第一个演示文稿然后却没有?

2 个答案:

答案 0 :(得分:1)

该错误告诉您它无法写入该文件路径,这意味着它不存在。在尝试将index.html写入writePath之前,应在markdownString方法中通过添加对FileManager.default.fileExists(atPath: kPath.path)的检查来确认这一点。

确认后,您需要跟踪HTML文件夹创建的生命周期(只需不断检查FileManager.default.fileExists(atPath: thePath),直到跟踪消失/未创建它为止。

根据您发布的代码,没有明显迹象表明发生这种情况的原因。它必须在您应用程序的其他地方。

答案 1 :(得分:0)

在您的更新部分中,您提到以下错误:
Failed to write html to file with error: Error Domain=NSCocoaErrorDomain Code=4 "The folder “index.html” doesn’t exist."
据我了解您的问题,index.html不应该是文件夹而是文件。

我不知道为什么它将index.html视为文件夹,但可能会替换为 let writePath = kPath.appendingPathComponent("index.html")

let writePath = kPath.appendingPathComponent("index.html", isDirectory: false)
帮助或至少导致更具体的错误消息。

相关问题