文件管理器有时在文档目录中找不到子文件夹
File Manager sometimes doesn't find subfolder in documents directory
我以前问过这个问题,但不得不重新表述所有内容以使其更容易理解。
在我的项目中,我使用以下代码在 documents directory
中创建了一个名为 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)")
}
}
打印语句打印如下:
Document directory is file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML
在我的应用程序 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)
}
}
}
}
我知道我可以通过将 HTML baseURL
设置为 main.Bundle
在应用程序的 Bundle
中同时使用两者,但是因为我需要在 HTML
中显示本地图像而不是网络链接的图像,我不得不将它们移动到一个子文件夹中,以便我以后将所需的图像复制到该子文件夹中,因为 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)
}
}
这是我的问题开始的地方。
swiss.css
文件位于以下目录中:
file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML/
HTML baseURL
指向以下路径:
file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML/
如您所见,它们都指向同一条路径。
有时我的 HTML
会找到 swiss.css
文件,因为它会在 do{}catch{}
块中打印 items
,但有时找不到文件夹, try fm.contentsOfDirectory(atPath: kPath.path)
引发在 catch{}
块打印以下内容时捕获的错误:
Error: Error Domain=NSCocoaErrorDomain Code=260 "The folder “HTML” doesn’t exist." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML, NSUserStringVariant=(
Folder
), NSUnderlyingError=0x1c044e5e0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
这在模拟器和真实设备上都会发生。
导致此问题的原因是什么?为什么它有时会找到文件夹而有时却找不到,即使没有重新启动应用程序,这可能会重置 documents directory
路径,即使我没有强制路径,而是我将其获取为你可以看到上面。
我不明白这种行为。
更新
所以我在想直接读取 html
字符串可能会导致一些问题,所以我更改了我的 markdown: String?
声明。
在其中,我将转换后的 markdown 字符串(不是 html 字符串)写入同一路径下的文件中,名为 index.html
.
现在人们认为发生了不同的事情——当我第一次推送这个视图时,它现在找到了我的 swiss.css
文件并且 html
文件检测到它并按预期使用它;到目前为止一切顺利。
但是 当我关闭这个视图控制器时,弹出到父视图控制器(按下后退按钮)然后尝试再次按下它,同样的错误(如前所述)提示:
Failed to write html to file with error: Error Domain=NSCocoaErrorDomain Code=4 "The folder “index.html” doesn’t exist." UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/C0639153-6BA7-40E7-82CF-25BA4CB4A943/Documents/HTML/index.html, NSUserStringVariant=Folder, NSUnderlyingError=0x1c045d850 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
请注意,这里的一些路径与之前的不同,因为它是不同的启动并且会发生变化,但这不是这里的问题,因为我从不存储路径并强制写入它,我总是获取 URL使用默认的文件管理器提取,
更新后的 markdown
声明如下:
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)
do {
let writePath = kPath.appendingPathComponent("index.html")
try html.write(to: writePath, atomically: true, encoding: .utf8)
webView.loadFileURL(writePath, allowingReadAccessTo: kPath)
} catch {
print("Failed to write html to file with error:", error)
return
}
let fm = FileManager.default
do {
let items = try fm.contentsOfDirectory(atPath: kPath.path)
print("items:", items)
} catch {
print("Error:", error)
}
}
}
不知何故,这让我更加困惑。
为什么它在第一个演示文稿中起作用,然后就不起作用了?
您在更新部分提到了以下错误:
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)
帮助或至少导致更具体的错误消息。
错误告诉您它无法写入该文件路径,这意味着它不存在。在尝试将 index.html 写入 writePath 之前,您应该在 markdownString 方法中通过添加对 FileManager.default.fileExists(atPath: kPath.path)
的检查来确认这一点。
确认后,您需要跟踪 HTML 文件夹创建的生命周期(只需不断检查 FileManager.default.fileExists(atPath: thePath)
直到找到 disappearing/not 的创建时间。
从您发布的代码来看,没有明显的迹象表明为什么会发生这种情况。它必须在您应用的其他地方。
我以前问过这个问题,但不得不重新表述所有内容以使其更容易理解。
在我的项目中,我使用以下代码在 documents directory
中创建了一个名为 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)")
}
}
打印语句打印如下:
Document directory is file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML
在我的应用程序 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)
}
}
}
}
我知道我可以通过将 HTML baseURL
设置为 main.Bundle
在应用程序的 Bundle
中同时使用两者,但是因为我需要在 HTML
中显示本地图像而不是网络链接的图像,我不得不将它们移动到一个子文件夹中,以便我以后将所需的图像复制到该子文件夹中,因为 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)
}
}
这是我的问题开始的地方。
swiss.css
文件位于以下目录中:
file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML/
HTML baseURL
指向以下路径:
file:///var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML/
如您所见,它们都指向同一条路径。
有时我的 HTML
会找到 swiss.css
文件,因为它会在 do{}catch{}
块中打印 items
,但有时找不到文件夹, try fm.contentsOfDirectory(atPath: kPath.path)
引发在 catch{}
块打印以下内容时捕获的错误:
Error: Error Domain=NSCocoaErrorDomain Code=260 "The folder “HTML” doesn’t exist." UserInfo={NSFilePath=/var/mobile/Containers/Data/Application/103869C9-9D46-4595-A370-A93BCD75D495/Documents/HTML, NSUserStringVariant=( Folder ), NSUnderlyingError=0x1c044e5e0 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
这在模拟器和真实设备上都会发生。
导致此问题的原因是什么?为什么它有时会找到文件夹而有时却找不到,即使没有重新启动应用程序,这可能会重置 documents directory
路径,即使我没有强制路径,而是我将其获取为你可以看到上面。
我不明白这种行为。
更新
所以我在想直接读取 html
字符串可能会导致一些问题,所以我更改了我的 markdown: String?
声明。
在其中,我将转换后的 markdown 字符串(不是 html 字符串)写入同一路径下的文件中,名为 index.html
.
现在人们认为发生了不同的事情——当我第一次推送这个视图时,它现在找到了我的 swiss.css
文件并且 html
文件检测到它并按预期使用它;到目前为止一切顺利。
但是 当我关闭这个视图控制器时,弹出到父视图控制器(按下后退按钮)然后尝试再次按下它,同样的错误(如前所述)提示:
Failed to write html to file with error: Error Domain=NSCocoaErrorDomain Code=4 "The folder “index.html” doesn’t exist." UserInfo={NSURL=file:///var/mobile/Containers/Data/Application/C0639153-6BA7-40E7-82CF-25BA4CB4A943/Documents/HTML/index.html, NSUserStringVariant=Folder, NSUnderlyingError=0x1c045d850 {Error Domain=NSPOSIXErrorDomain Code=2 "No such file or directory"}}
请注意,这里的一些路径与之前的不同,因为它是不同的启动并且会发生变化,但这不是这里的问题,因为我从不存储路径并强制写入它,我总是获取 URL使用默认的文件管理器提取,
更新后的 markdown
声明如下:
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)
do {
let writePath = kPath.appendingPathComponent("index.html")
try html.write(to: writePath, atomically: true, encoding: .utf8)
webView.loadFileURL(writePath, allowingReadAccessTo: kPath)
} catch {
print("Failed to write html to file with error:", error)
return
}
let fm = FileManager.default
do {
let items = try fm.contentsOfDirectory(atPath: kPath.path)
print("items:", items)
} catch {
print("Error:", error)
}
}
}
不知何故,这让我更加困惑。
为什么它在第一个演示文稿中起作用,然后就不起作用了?
您在更新部分提到了以下错误:
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)
帮助或至少导致更具体的错误消息。
错误告诉您它无法写入该文件路径,这意味着它不存在。在尝试将 index.html 写入 writePath 之前,您应该在 markdownString 方法中通过添加对 FileManager.default.fileExists(atPath: kPath.path)
的检查来确认这一点。
确认后,您需要跟踪 HTML 文件夹创建的生命周期(只需不断检查 FileManager.default.fileExists(atPath: thePath)
直到找到 disappearing/not 的创建时间。
从您发布的代码来看,没有明显的迹象表明为什么会发生这种情况。它必须在您应用的其他地方。