我以前曾问过这个问题,但不得不重新制定一切,以便更容易理解。
在我的项目中,我使用以下代码在名为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
不知何故,这让我更加困惑。
为什么它适用于第一个演示文稿然后却没有?
答案 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)
帮助或至少导致更具体的错误消息。