2017-12-12 13 views
9

私は以前これを尋ねましたが、もっと分かりやすいようにすべてを再構成する必要がありました。私のプロジェクトで ファイルマネージャで文書ディレクトリのサブフォルダが見つからない場合があります

が、私は次のコードで呼ば documents directory HTML内部のサブフォルダを作成しました:私は私のアプリの Bundleインサイド

Document directory is 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)") 
    } 
} 

print文は、次の印刷します私がHTML文字列で使用するファイルはWKWebViewに表示されます。

.cssファイルがHTML baseURLと同じフォルダにあることが必要であるとして、私は次のコードで上記の関数で作成したディレクトリにBundleから.cssファイル、そのコピー:

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 baseURLmain.Bundleに設定して使うことができましたが、HTMLのローカル画像を表示する必要があり、Webリンクされた画像ではないため、それらをサブフォルダに移動して後でmain.Bundleから、そのサブフォルダに必要な画像読み取り専用であり、書き込み可能ではありません(画像は保存できません)。

ViewControllerUINavigationControllerにプッシュされています。その中にプッシュViewController私はを提示するWKWebViewを持っています。

私もかつて、私は次の関数を使用してHTML文字列に変換し、インスタンス化var markdownString: String? {}プロパティがあります。

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にロードしますgコード:

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は、それがdo{}catch{}ブロックでitemsを印刷して、swiss.cssファイルを見つけたが、それは、フォルダを見つけることができません。他の回、try fm.contentsOfDirectory(atPath: kPath.path)火災エラーは、次の印刷catch{}ブロックにcatched:

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のパスをリセットするかもしれない、アプリケーションを再起動しなくても時々、それは時々そしてそれ以外の時にフォルダを見つけるのですが、私はあなたが上記のようにそれをフェッチしています。

この現象はわかりません。

UPDATE

だから私は、私は私のmarkdown: String?宣言を変更してhtml文字列の読み取りが直接いくつかの問題を引き起こしている可能性がありますことを考えていました。

私は変換されたマークダウン文字列(HTML文字列ではありません)をindex.htmlという同じパスのファイルに書き込みます。

このビューを初めてプッシュすると、今度はswiss.cssファイルが見つかり、htmlファイルがそのファイルを検出して期待通りに使用するようになりました。ここまでは順調ですね。

しかし私は(バックボタンを押す)親ビューコントローラにpoping、このビューコントローラを閉じてから、再度それをプッシュしようとすると、(前述の)同じエラーが求められます。

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"}}

ここではいくつかのパスは以前のものとは異なっていますが、これは別の起動で変更されるためですが、パスを保存せず強制的に書き込むことがないため、ここでは問題はありません。 fetch、

更新された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) 
     } 
    } 
} 

何とか私はさらに混乱しています。

なぜ最初のプレゼンテーションでは動作しますか?あなたのUPDATE]セクションで

+0

この「css」にタグを付けた理由を聞いてもよろしいですか?どのくらい正確にCSSの専門家がこの質問にあなたを助けることができましたか? –

+0

@AndreiGheorghiuあなたは正しいです。それは間違いだった。 –

+0

固定 "guard let str = markdownString else {return}"これは疑わしいコードの唯一の部分です。 – Mozahler

答えて

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", isDirectory: false)

let writePath = kPath.appendingPathComponent("index.html")
を交換します。

+1

それは奇妙な部分です。エラーを記録するコードを置き換えることさえできます。私はなぜそれが起こっているのか分からない。私は前進し、このコード部分を書き直して別のアプローチをとると思います。それから別に私はそれを理解するために深く考えます。 –