ios - support - wkwebview navigation swift
WKWebView agregado como subvista no cambia de tamaño en rotación en Swift (4)
Logré resolver el problema usando esta línea de código:
self._webView!.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
:)
Estoy trabajando para agregar una nueva vista de lectura a mi aplicación de navegador. Es otro controlador de vista, que solo incluye un WKWebView agregado como una subvista con un botón (y un gesto) para cerrar la vista. Todo funciona muy bien, pero cuando giro el dispositivo, la subvista no cambia de tamaño, por lo que tengo la mitad de la pantalla vacía.
El WKWebView en la Vista de lectura obtiene la URL del controlador de vista principal con una transición realizada después de que el usuario toca un botón en el controlador de vista principal y esa URL se almacena como URL de página.
Aquí está el código que utilicé:
import UIKit
import WebKit
class ReadingViewController: UIViewController, UIGestureRecognizerDelegate, WKNavigationDelegate, WKScriptMessageHandler {
@IBOutlet weak var _closeButton: UIButton!
@IBOutlet weak var _progressView: UIProgressView!
@IBOutlet weak var _loadingErrorView: UIView!
var webpageURL: NSURL?
var _webView: WKWebView?
var _isMainFrameNavigationAction: Bool?
var _loadingTimer: NSTimer?
var _swipeFromTopRecognizer: UIScreenEdgePanGestureRecognizer?
var _panFromRightRecognizer: UIScreenEdgePanGestureRecognizer?
var _panFromLeftRecognizer: UIScreenEdgePanGestureRecognizer?
var _errorView: UIView?
var _isCurrentPageLoaded = false
var _progressTimer: NSTimer?
var _isWebViewLoading = false
override func viewDidLoad() {
super.viewDidLoad()
var contentController = WKUserContentController();
var scaleToFit = WKUserScript(source: "var meta = document.createElement(''meta''); meta.setAttribute(''name'', ''viewport''); meta.setAttribute(''content'', ''width=device-width''); document.getElementsByTagName(''head'')[0].appendChild(meta);", injectionTime: WKUserScriptInjectionTime.AtDocumentStart, forMainFrameOnly: true)
contentController.addUserScript(scaleToFit)
contentController.addScriptMessageHandler(self, name: "callbackHandler")
var webViewConfiguration: WKWebViewConfiguration = WKWebViewConfiguration()
webViewConfiguration.allowsInlineMediaPlayback = true
webViewConfiguration.mediaPlaybackRequiresUserAction = false
_webView = WKWebView(frame: self.view.frame, configuration: webViewConfiguration)
self.view.addSubview(_webView!)
_webView!.navigationDelegate = self
self.view.sendSubviewToBack(_webView!)
_webView!.allowsBackForwardNavigationGestures = true
_loadingErrorView.hidden = true
_swipeFromTopRecognizer = UIScreenEdgePanGestureRecognizer(target: self, action: Selector("handleSwipeFromTop:"))
_swipeFromTopRecognizer!.edges = UIRectEdge.Top
_swipeFromTopRecognizer!.delegate = self
self.view.addGestureRecognizer(_swipeFromTopRecognizer!)
_progressView.hidden = true
var urlAsString = "/(webpageURL!)"
loadURL(urlAsString)
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
// UI Control Functions
func gestureRecognizer(gestureRecognizer: UIGestureRecognizer, shouldRecognizeSimultaneouslyWithGestureRecognizer otherGestureRecognizer: UIGestureRecognizer) -> Bool {
return true
}
@IBAction func closeReadingView(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
func closeButtonEnabled(bool:Bool) {
_closeButton.enabled = bool
}
func userContentController(userContentController: WKUserContentController, didReceiveScriptMessage message: WKScriptMessage) {
if(message.name == "callbackHandler") {
println("JavaScript is sending a message /(message.body)")
}
}
// WebView Functions
func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
_loadingErrorView.hidden = true
_isWebViewLoading = true
_progressView.hidden = false
_progressView.progress = 0
_progressTimer = NSTimer.scheduledTimerWithTimeInterval(0.01667, target: self, selector: "progressTimerCallback", userInfo: nil, repeats: true)
_loadingTimer = NSTimer.scheduledTimerWithTimeInterval(30, target: self, selector: "loadingTimeoutCallback", userInfo: nil, repeats: false)
}
func loadingTimeoutCallback() {
_webView?.stopLoading()
handleWebViewError()
}
func webView(webView: WKWebView, didCommitNavigation navigation: WKNavigation!) {
_isCurrentPageLoaded = true
_loadingTimer!.invalidate()
_isWebViewLoading = false
if self._webView!.URL == webpageURL! {
handleWebViewError()
println(webpageURL!)
println(self._webView!.URL!)
} else {
println("Page was loaded successfully")
println(webpageURL!)
println(self._webView!.URL!)
}
}
func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) {
_isCurrentPageLoaded = true
_loadingTimer!.invalidate()
_isWebViewLoading = false
}
func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) {
if let newFrameLoading = _isMainFrameNavigationAction {
} else {
handleWebViewError()
}
}
func webView(webView: WKWebView, didFailNavigation navigation: WKNavigation!, withError error: NSError) {
if let newFrameLoading = _isMainFrameNavigationAction {
} else {
handleWebViewError()
}
}
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) {
if (navigationAction.targetFrame == nil && navigationAction.navigationType == .LinkActivated) {
_webView!.loadRequest(navigationAction.request)
}
_isMainFrameNavigationAction = navigationAction.targetFrame?.mainFrame
decisionHandler(.Allow)
}
func handleWebViewError() {
_loadingTimer!.invalidate()
_isCurrentPageLoaded = false
_isWebViewLoading = false
displayLoadingErrorMessage()
}
func progressTimerCallback() {
if (!_isWebViewLoading) {
if (_progressView.progress >= 1) {
_progressView.hidden = true
_progressTimer?.invalidate()
} else {
_progressView.progress += 0.2
}
} else {
_progressView.progress += 0.003
if (_progressView.progress >= 0.95) {
_progressView.progress = 0.95
}
}
}
func loadURL(urlString: String) {
let addrStr = httpifyString(urlString)
let readingAddr = addrStr.stringByAddingPercentEncodingForFormUrlencoded()!
let addr = NSURL(string: "http://mobilizer.instapaper.com/m?u=/(readingAddr)")
if let webAddr = addr {
let req = NSURLRequest(URL: webAddr)
_webView!.loadRequest(req)
} else {
displayLoadingErrorMessage()
}
}
func httpifyString(str: String) -> String {
let lcStr:String = (str as NSString).lowercaseString
if (count(lcStr) >= 7) {
if (lcStr.rangeOfString("http://") != nil) {
return str
} else if (lcStr.rangeOfString("https://") != nil) {
return str
}
}
return "http://"+str
}
func displayLoadingErrorMessage() {
_loadingErrorView.hidden = false
}
func handleGoBackPan(sender: UIScreenEdgePanGestureRecognizer) {
if (sender.state == .Ended) {
_webView!.goBack()
}
}
func handleGoForwardPan(sender: AnyObject) {
if (sender.state == .Ended) {
_webView!.goForward()
}
}
func handleSwipeFromTop(sender: AnyObject) {
self.dismissViewControllerAnimated(true, completion: nil)
}
override func viewWillTransitionToSize(size: CGSize, withTransitionCoordinator coordinator: UIViewControllerTransitionCoordinator) {
coordinator.animateAlongsideTransition({ context in
self._webView!.frame = CGRectMake(0, 0, size.width, size.height)
}, completion: nil)
}
}
Y aquí hay algunas capturas de pantalla para demostrar el problema: esta es la vista después de que terminó de cargarse y funciona correctamente:
Esta es la vista después de rotar el dispositivo al paisaje:
Y esta es la ubicación de desplazamiento después de la rotación:
El uso de self.view = _webView hace que la vista cambie de tamaño correctamente, pero ignora todas las vistas en el Guión gráfico (ya que los contenidos de la Vista se están reescribiendo).
¿Cómo puedo solucionar este problema (sin reescribir self.view)?
Estoy publicando una respuesta para Objective-C, por si acaso alguien viene aquí buscándola
[self.webView setAutoresizingMask:UIViewAutoresizingFlexibleHeight | UIViewAutoresizingFlexibleWidth];
versión rápida 3:
webView?.autoresizingMask = [.flexibleWidth, .flexibleHeight]
De hecho, como WKWebView solo se puede agregar mediante programación, tiene la máscara de aumento automático a la marca de restricciones activada de manera predeterminada (al agregar componentes y restricciones dentro de Interface Builder, generalmente está deshabilitada). Creo que la solución correcta sería:
webView?.translatesAutoresizingMaskIntoConstraints = false
después de agregar las restricciones / anclas.