WKWebView не загружает URL-адрес https?
У меня есть WKWebView, который должен загрузить следующий URL:
https://buchung.salonmeister.de/place/#offer-details-page?id=907599&venueId=301655
Вот код, который я использую:
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
}
}
}
}
Примечание. Я использую SDK iOS 8.4
Почему мобильный Safari загружает этот URL-адрес, но WKWebView
не работает?
Ответы
Ответ 1
Добавьте это в свой plist
<key>NSAppTransportSecurity</key>
<dict>
<key>NSAllowsArbitraryLoads</key>
<true/>
</dict>
Здесь объяснение этого изменения в 9.0
http://ste.vn/2015/06/10/configuring-app-transport-security-ios-9-osx-10-11/
Также, если вы хотите установить его более безопасным, это даст вам более сложный способ сделать это.
Ответ 2
Для меня проблема была вызвана проверкой доверия сервера из WKWebView.
Чтобы это исправить, я должен был обработать обратный вызов аутентификации вызова и вернуть учетные данные доверия сервера.
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)
}
}
Ответ 3
У меня была аналогичная проблема с сайтом, который также был защищен сертификатом TLS 1.2 высокой безопасности. Чтобы заставить WKWebView принять сертификат сервера, я добавил этот код к моему делегату контроллера веб-представления:
-(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);
}
}
Ответ 4
Не уверен, что с той же ошибкой, но проблема была одинаковой для меня в iOS9
некоторые домены не могут быть загружены
оказалось, что проблема была в
- (void)webView:(WKWebView *)webView didReceiveAuthenticationChallenge:(NSURLAuthenticationChallenge *)challenge completionHandler:(void (^)(NSURLSessionAuthChallengeDisposition, NSURLCredential *))completionHandler {
и обеспечение назад
completionHandler(NSURLSessionAuthChallengeCancelAuthenticationChallenge, nil);
где я должен был бы вернуть
completionHandler(NSURLSessionAuthChallengePerformDefaultHandling, nil);
Я использовал WRONG-код из https://github.com/ShingoFukuyama/WKWebViewTips
Ответ 5
// 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>
Если WKWebView не поддерживает, объявите файл .m под кодом:
введите код сюда
@interface WebScannerViewController()
{
WKWebView *webView;
}
@конец
@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);
}
Ответ 6
Если вы находитесь в изолированном MacOS-приложении, вам нужно настроить возможность исходящих подключений (клиента), вам не нужно связываться с Allow Abitrary Loads, которые не должны вступать в игру для запросов https. ![Xcode Capabilities Screenshot showing the Outgoing Connections (Client) checkbox checked]()
Однако для iOS разрешение клиентских подключений используется по умолчанию, поэтому вам может потребоваться реализовать методы WKNavigationDelegate
для обеспечения безопасности. Убедитесь, что вы не просто доверяете ненадежным сертификатам. Это видео о Swift Talk от objc.io - лучший из известных мне ресурсов, определенно стоит 20 минут, если вы работаете в этой области: https://talk.objc.io/episodes/S01E57-certificate-pinning