Appleの推奨 :
IOS 8以降で実行されるアプリでは、UIWebViewを使用する代わりにWKWebViewクラスを使用します。
したがって、私は古き良きUIWebView
を光沢のある新しいWKWebView
に置き換えました。しかし、簡単な演習(単純にクラスを交換し、デリゲートメソッドを置き換える)であると思ったのは、実際の混乱でした。
を使用してHTML文字列を読み込むとき
_loadHTMLString(String, baseURL: URL?)
_
webビューは純粋なHTMLをロードしてレンダリングしますが、htmlString
内で参照される画像やCSSファイルはロードしません。
これは実際のデバイスでのみ発生します!
Simultorでは、参照されるすべてのリソースが正しくロードされます。
View Controllerクラスで単純なhtmlString
を定義しました。
_let imageName = "image.png"
let libraryURL: URL // The default Library URL
var htmlString: String {
return "<html> ... <img src=\"\(imageName)\" /> ... </html>"
// "..." represents more valid HTML code incl. header and body tags
}
_
画像はルートライブラリフォルダに保存されるため、URLは次のとおりです。
_let imageURL = libraryURL.appendingPathComponent(imageName)
_
次に、htmlString
をWebビューにロードします。
_webView.loadHTMLString(htmlString, baseURL: libraryURL)
_
baseURL
が正しく設定されていても、画像はロードされません。
おそらくWKWebView
には相対パスの解決に問題があるので、私の最初のアイデアは、代わりにHTML文字列内で絶対パスを使用することでした。
→❌機能しません。
another SO post への2つの答えは、loadFileURL(URL, allowingReadAccessTo: URL)
loadHTMLString(...)
の代わりにiOS 9以降で動作します。
→✅動作します。
ただし、HTMLファイルは暗号化されており、復号化されたファイルはディスクに保存してはならないため、ソリューション2は使用できません。
WKWebView
を使用して画像やスタイルなどのローカルリソースをロードする方法はありますか
_loadHTMLString(String, baseURL: URL?)
_
関数?または、まだiOS 9以降のバグですか?
(AppleはHTML文字列内からローカルWebコンテンツをロードできないWebビューの使用を提供および推奨しますか?!)
実際のプロジェクトを見ていないと、百パーセントの確実なアドバイスを与えることは困難です。
しかしながら:
class ViewController: UIViewController {
var webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
webView.translatesAutoresizingMaskIntoConstraints = false
let views = [
"webView" : webView
]
view.addSubview(webView)
var constraints = NSLayoutConstraint.constraintsWithVisualFormat("H:|[webView]|", options: [.AlignAllLeading, .AlignAllTrailing], metrics: nil, views: views)
constraints.appendContentsOf(NSLayoutConstraint.constraintsWithVisualFormat("V:|[webView]|", options: [.AlignAllTop, .AlignAllBottom], metrics: nil, views: views))
NSLayoutConstraint.activateConstraints(constraints)
let path = NSBundle.mainBundle().pathForResource("ios - WKWebView fails to load images and CSS using loadHTMLString(_, baseURL_) - Stack Overflow", ofType: "htm")
let url = NSURL(fileURLWithPath: path!)
webView.loadHTMLString(try! String(contentsOfURL: url), baseURL: url.URLByDeletingLastPathComponent)
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
}
ここでのキーポイントはbaseUrl
パラメーターだと思うので、正しく設定する必要があります。私の場合、私は最後のパスコンポーネントなしでhtmlのURLを使用しました-例えばフォルダーを含む。これは、デバイスとシミュレータの両方で正常に動作します-デバイスのスナップショットを確認してください。サンプルプロジェクトを https://github.com/soxjke/WKWebViewTest にアップロードしたので、ご覧ください(gitからコード署名情報を削除しました)
要約すると、メソッドは機能し、機能は機能していますが、あなたは何か間違ったことをしています。ソリューションの問題を解決するために、いくつかの提案を追加します。1.シミュレータファイルシステムはcase-insensitiveであり、デバイスファイルシステムは大文字と小文字を区別します。そのため、ファイル名が小文字のhtmlにある場合、これはデバイス上では機能しません。 8fFsD.png != 8ffsd.png
2.リソースをコピーするとき、XCodeはフォルダー構造を無視することに注意してください。したがって、HTMLに<img src="./img/1.png">
そしてあなたのXCOdeプロジェクトは次のようなフォルダ構造を持っています
test.htm
img/
1.png
2.png
ビルド後はフラット化されるため、test.htmと1.pngおよび2.pngは同じレベルに存在します
test.htm
1.png
2.png
これら2つの仮定を検証した後、このメソッドが機能することはほぼ確実です。
私は今日この問題を抱えていました、私は解決策と潜在的に原因を見つけました:
loadHTMLString(String, baseURL: URL?)
私が知っている限り、この関数はレンダリングされたHTMLがローカルメディアにアクセスすることを許可しません。これはインジェクションのリスクがあるためです。これにより、レンダリングされたHTMLがローカルファイルシステムにアクセスして操作できるようになります。 HTML文字列を使用すると、どこからでも、または誰からでも送信できます。
loadFileURL(URL, allowingReadAccessTo: URL)
この関数を使用して、FileManagerのhtmlファイルと、「allowingReadAccessTo」を含むフォルダーをWKWebviewにポイントします。 htmlはFileManager内に保存されるため、レンダリングされたHTMLがローカルに保存されたメディアにアクセスできます。
何らかの理由でhtmlファイルがローカルに保存されていない場合(そうすることを前提としています)、. htmlファイルにhtmlスティングを書き込み、そのファイルのURLをポイントできます。ただし、これはAppleの保護を破壊するだけなので、自分の責任で実行してください(実行しないでください)。
これはちょうど私のために働いた解決策であり、最初に問題を抱えている理由を理解しています。
編集#1:タイプミス。
編集#2:「allowingReadAccessTo:」URLを指定するときに、HTML自体が親フォルダー(.css、.jsファイル)にアクセスする必要がある場合、別のニュアンスを見つけました。親フォルダーを指定する必要があります。 、必ずしもHTML自体の場所ではありません。これにより、必要に応じて子フォルダーへのアクセスも暗黙的に許可されます。私にとって、この問題は物理デバイスでのみ明らかでした。これは、シミュレーターでの実行中には効果がないようでした。おそらく、シミュレーターと物理デバイスでの権限の動作の間に別の矛盾があります。
既に見つけた機能を備えたWKWebViewsで、ローカルイメージとCSSファイル(およびそのためのJavaScriptファイル)を使用できるはずです。私の推測では、問題はbaseURL
変数にあるということです。
7.5.2017の更新:
another SO answer からのコードを完全に更新しました。以前はここで私の答えにリンクされていました。loadHTMLString()
の作業プロジェクトがあります。および.loadFileURL()
画像をbase64でエンコードできます...私はそれが機能することを知っています。ただし、ユースケースに適しているかどうかはわかりません。
ちょっとおかしいのですが、反対のことをしながらこの問題に遭遇しました-base64エンコードから画像ファイルに移行しました。
個人的には、 XWebView を使用するように切り替える必要がありました。WKWebViewの初期状態の動作ではローカルファイルの読み込みが許可されていないためです。 XWebViewは、バックグラウンドでローカルWebサーバーをロードし、それを介してローカルトラフィックを誘導することにより、それをtrickします。 (XWebViewはWKWebViewのトップに基づいています)
少しやり過ぎのようですが、それが私がやらなければならなかったことです。
私も同様の制限でこれを実験してきましたが、問題はbaseURL
がアプリケーションバンドルを参照しない限りパスが解決されないことです。たとえば、アプリケーションのドキュメントに何かがあると機能しません。
編集:これについてレーダーを提出しました rdar:// 2913086
同様の問題を再現することができました。 WKWebViewは、アプリサーバーとは別に、リモートに配置されている画像を特別に読み込みます。
SSLで保護されていないサーバー(httpsではなくhttp)では、以下のようにinfo.plist
を設定できます。
App Transport Security Settings
- Allow Arbitrary Loads in Web Content (Set to YES)
- Allow Arbitrary Loads (Set to YES)
問題は実際にサーバーにありました。サーバーアプリケーションは次のいずれかでした。
"http://IP-or-domain/uploads/file.jpg"
から"../../uploads/file.jpg"
に変更しています-OR-
"http://localhost/uploads/file.jpg"
または"http://127.0.0.1/uploads/file.jpg"
の代わりに"http://YOUR-SERVER-IP-ADDRESS/uploads/file.jpg"
でしたこれらの場合、実際のデバイスは画像を見つけることができません。仮想デバイスはサーバーおよび開発マシンと同じであるため、これはiOSシミュレーターでのみ機能します。 LOCALHOST
および127.0.0.1
を読み取ることができます。
私のサーバーでは、リッチテキストエディター(TinyMCE)を使用しており、同じソースであることを検出した後、IPアドレスを自動的に削除します。
次を使用してbaseURL
を作成してみてください。
let baseURL = URL(fileURLWithPath: "#path#")
の代わりに:
let baseURL = URL(string: "#path#")
主な違いは、最初のメソッドがパスの前にfile://
プレフィックスを追加することです。