Iva*_*ino 10 ios swift wkwebview
我以前曾问过这个问题,但不得不重新制定一切,以便更容易理解.
在我的项目中,我使用以下代码在被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)")
}
}
Run Code Online (Sandbox Code Playgroud)
print语句打印以下内容:
文件目录是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)
}
}
}
}
Run Code Online (Sandbox Code Playgroud)
我知道我可以同时使用在应用程序的Bundle
通过设置HTML baseURL
的main.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!
}
Run Code Online (Sandbox Code Playgroud)
我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
}()
Run Code Online (Sandbox Code Playgroud)
每当我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)
}
}
Run Code Online (Sandbox Code Playgroud)
这是我的问题开始的地方.
该swiss.css
文件位于以下目录中:
文件:///无功/移动/集装箱/数据/应用/ 103869C9-9D46-4595-A370-A93BCD75D495 /文件/ HTML /
HTML baseURL
指向以下路径的点:
文件:///无功/移动/集装箱/数据/应用/ 103869C9-9D46-4595-A370-A93BCD75D495 /文件/ HTML /
如你所见,他们都指向同一条道路.
有时我会HTML
找到该swiss.css
文件,因为它items
在do{}catch{}
块中打印,但有时它找不到文件夹,try fm.contentsOfDirectory(atPath: kPath.path)
会在catch{}
块中触发错误,打印以下内容:
错误:错误域= NSCocoaErrorDomain代码= 260"文件夹"HTML"不存在." 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文件或目录"}}
这两种情况都发生在模拟器和真实设备上.
是什么导致了这个问题?为什么它有时会找到该文件夹,有时却没有找到它,即使没有重新启动应用程序,这可能会重置documents directory
路径,即使我没有强制路径,而是我正在提取它,如上所示.
我不明白这种行为.
UPDATE
所以我认为html
直接读取字符串可能会导致一些问题所以我改变了我的markdown: String?
声明.
在其中,我将转换后的markdown字符串(不是html字符串)写入同一路径中的文件中,称为index.html
.
现在有人认为发生了不同的事情 - 当我第一次推送这个视图时,它现在找到我的swiss.css
文件并且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"没有这样的文件或目录"}}
请注意,这里的一些路径与之前的路径不同,因为它是一个不同的启动并且它会发生变化,但这不是问题,因为我从不存储路径并强制写入它,我总是使用默认的文件管理器获取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)
}
}
}
Run Code Online (Sandbox Code Playgroud)
不知怎的,这让我更加困惑.
为什么它适用于第一个演示文稿然后它没有?
小智 1
该错误告诉您它无法写入该文件路径,这意味着它不存在。FileManager.default.fileExists(atPath: kPath.path)
在尝试将 index.html 写入 writePath 之前,您应该在 markdownString 方法中添加检查来确认这一点。
确认后,您需要跟踪 HTML 文件夹创建的生命周期(只需继续检查,FileManager.default.fileExists(atPath: thePath)
直到找到它消失/未创建的时间。
从您发布的代码来看,没有明显的迹象表明为什么会发生这种情况。它必须位于应用程序中的其他位置。
归档时间: |
|
查看次数: |
546 次 |
最近记录: |