Ich habe eine WKWebView, die folgende URL laden sollte:
https://buchung.salonmeister.de/place/#offer-details-page?id=907599&venueId=301655
Ihr ist der Code, den ich verwende:
import UIKit
import WebKit
class MMWKBrowserController: UIViewController {
private let closeButtonSelector: Selector = "closeButtonTapped:"
private var urlString: String
private let request: NSMutableURLRequest
private var webView: WKWebView!
private var twoLineTitleView: UIView!
private var titleLabel: UILabel?
private var subTitleLabel: UILabel?
private var indicator: UIActivityIndicatorView!
init(urlString: String) {
self.urlString = urlString
println("*** Using MMWKBrowserController ***")
var url: NSURL? = NSURL(string: urlString)
if url == nil {
var escapedString: String = urlString.stringByAddingPercentEscapesUsingEncoding(NSUTF8StringEncoding)!
self.urlString = escapedString
url = NSURL(string: escapedString)
}
println("url: \(url)")
request = NSMutableURLRequest(URL: url!)
request.setValue("Mozilla/5.0 (iPhone; CPU iPhone OS 8_4 like Mac OS X) AppleWebKit/600.1.4 (KHTML, like Gecko) Version/8.0 Mobile/12H141 Safari/600.1.4", forHTTPHeaderField: "UserAgent")
super.init(nibName: nil, bundle: nil)
}
required init(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
deinit {
self.webView.removeObserver(self, forKeyPath: "loading")
self.webView.removeObserver(self, forKeyPath: "title")
self.webView.removeObserver(self, forKeyPath: "URL")
self.webView.removeObserver(self, forKeyPath: "estimatedProgress")
self.webView.stopLoading()
}
override func viewDidLoad() {
super.viewDidLoad()
createNavigationView()
self.navigationController?.navigationBar.tintColor = MGColor.actionColor
let config = WKWebViewConfiguration()
self.webView = WKWebView(frame: self.view.bounds, configuration: config)
self.view.addSubview(self.webView)
indicator = UIActivityIndicatorView(activityIndicatorStyle: UIActivityIndicatorViewStyle.Gray)
//indicator.backgroundColor = UIColor(white: 0.1, alpha: 0.5)
webView.addSubview(indicator)
self.webView.snp_makeConstraints { (make) -> Void in
make.edges.equalTo(self.view)
}
indicator.snp_makeConstraints { (make) -> Void in
make.center.equalTo(self.webView)
}
webView.addObserver(self, forKeyPath: "loading", options: NSKeyValueObservingOptions.New, context: nil)
webView.addObserver(self, forKeyPath: "title", options: NSKeyValueObservingOptions.New, context: nil)
webView.addObserver(self, forKeyPath: "URL", options: NSKeyValueObservingOptions.New, context: nil)
webView.addObserver(self, forKeyPath: "estimatedProgress", options: NSKeyValueObservingOptions.New, context: nil)
}
override func viewDidDisappear(animated: Bool) {
super.viewDidDisappear(animated)
self.webView.stopLoading()
}
private func createNavigationView() {
let closeItem = UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.Stop, target: self, action: closeButtonSelector)
self.navigationItem.leftBarButtonItem = closeItem
// create center view
let titleViewWidth = self.view.frame.size.width - 100
twoLineTitleView = UIView(frame: CGRectMake(0, 0, titleViewWidth, 44))
titleLabel = UILabel(frame: CGRectMake(0, 6, titleViewWidth, 16))
titleLabel?.backgroundColor = UIColor.clearColor()
titleLabel?.font = UIFont.boldSystemFontOfSize(16)
titleLabel?.textAlignment = NSTextAlignment.Center
subTitleLabel = UILabel(frame: CGRectMake(0, 21, titleViewWidth, 20))
subTitleLabel?.backgroundColor = UIColor.clearColor()
subTitleLabel?.font = UIFont.systemFontOfSize(10)
subTitleLabel?.textAlignment = NSTextAlignment.Center
twoLineTitleView.addSubview(titleLabel!)
twoLineTitleView.addSubview(subTitleLabel!)
self.navigationItem.titleView = twoLineTitleView
}
override func viewWillAppear(animated: Bool) {
super.viewWillAppear(animated)
self.webView.loadRequest(self.request)
}
func closeButtonTapped(sender: UIBarButtonItem) {
self.presentingViewController?.dismissViewControllerAnimated(true, completion: nil)
}
override func observeValueForKeyPath(keyPath: String, ofObject object: AnyObject, change: [NSObject : AnyObject], context: UnsafeMutablePointer<Void>) {
if let wk = object as? WKWebView {
switch keyPath {
case "loading":
if let val: AnyObject = change[NSKeyValueChangeNewKey] {
if let val = val as? Bool {
if val {
self.indicator.startAnimating()
}
else {
self.indicator.stopAnimating()
}
}
}
case "title":
self.titleLabel?.text = self.webView.title
case "URL":
self.subTitleLabel?.text = self.webView.URL?.URLString
case "estimatedProgress":
println("progress: \(Int32(self.webView.estimatedProgress*100))")
default: break
}
}
}
}
Hinweis: Ich verwende SDK iOS 8.4
Warum lädt mobile Safari diese URL, WKWebView
jedoch nicht?
Fügen Sie dies Ihrer Liste hinzu
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Hier ist die Erklärung für diese Änderung in 9.0 http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/
Auch wenn Sie es sicherer einrichten möchten, gibt es einen komplexeren Weg, dies zu tun.
Für mich wurde das Problem durch die Überprüfung der Server-Vertrauenswürdigkeit in der WKWebView verursacht.
Um dieses Problem zu beheben, musste ich den Challenge-Authentication-Callback behandeln und einen Berechtigungsnachweis für den Server zurückgeben.
Swift 4
func webView(_ webView: WKWebView,
didReceive challenge: URLAuthenticationChallenge,
completionHandler: @escaping (URLSession.AuthChallengeDisposition, URLCredential?) -> Void)
{
if(challenge.protectionSpace.authenticationMethod == NSURLAuthenticationMethodServerTrust)
{
let cred = URLCredential(trust: challenge.protectionSpace.serverTrust!)
completionHandler(.useCredential, cred)
}
else
{
completionHandler(.performDefaultHandling, nil)
}
}
Ich hatte ein ähnliches Problem mit einer Site, die ebenfalls mit einem TLS 1.2-Zertifikat mit hoher Sicherheit geschützt war. Damit WKWebView das Serverzertifikat akzeptiert, fügte ich diesen Code zu meinem Controller für die Webansicht hinzu:
-(void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential * _Nullable))completionHandler
{
if ([[[challenge protectionSpace]authenticationMethod] isEqualToString: @"NSURLAuthenticationMethodServerTrust"]) {
SecTrustRef serverTrust = challenge.protectionSpace.serverTrust;
CFDataRef exceptions = SecTrustCopyExceptions(serverTrust);
SecTrustSetExceptions(serverTrust, exceptions);
CFRelease(exceptions);
newCredential = [NSURLCredential credentialForTrust:serverTrust];
completionHandler(NSURLSessionAuthChallengeUseCredential, newCredential);
} else {
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, newCredential);
}
}
ich bin nicht sicher, ob der gleiche Fehlergrund vorliegt, aber das Problem war für mich unter iOS9 das gleiche
einige Domains konnten nicht geladen werden
stellte sich heraus, dass das Problem in war
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
und wieder zur Verfügung stellen
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
wo ich hätte zurückkehren sollen
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
Ich habe falschen Code von https://github.com/ShingoFukuyama/WKWebViewTips verwendet.
// Add plist file
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
<key>NSExceptionDomains</key>
<dict>
<key>google.com</key>
<dict>
<key>NSExceptionAllowsInsecureHTTPLoads</key>
<true/>
<key>NSIncludesSubdomains</key>
<true/>
</dict>
</dict>
wenn WKWebView nicht unterstützt wird, deklarieren Sie die .m-Datei unter dem folgenden Code:
code hier eingeben
@interface WebScannerViewController()
{
WKWebView *webView;
}
@Ende
@implementation WebScannerViewController - (void) viewDidLoad {
[super viewDidLoad];
webView.hidden=YES;
webView.UIDelegate = self;
webView.navigationDelegate = self;
self.loadingSign.hidden = NO;
webView.frame=CGRectMake(0, 94, Width, Height-128);
}
Wenn Sie sich in einer Sandkasten-MacOS-App befinden, müssen Sie die Outgoing Connections (Client) -Funktion einstellen. Sie müssen sich nicht mit Allow Abitrary Loads ändern, das für vertrauenswürdige https nicht zum Tragen kommen sollte Anfragen.
Für iOS ist das Erlauben von Clientverbindungen jedoch die Standardeinstellung. Daher müssen Sie möglicherweise WKNavigationDelegate
-Methoden implementieren, um die Sicherheit zu gewährleisten. Stellen Sie jedoch sicher, dass Sie nicht nur nicht vertrauenswürdigen Zertifikaten vertrauen. Dieses Swift Talk-Video von objc.io ist die beste Ressource, die ich kenne, und ist auf jeden Fall 20 Minuten wert, wenn Sie in diesem Bereich arbeiten: https://talk.objc.io/episodes/S01E57-certificate-pinning