Pregunta La hoja de acción WKWebView despide el controlador de vista de presentación después de ser despedido


Tengo un controlador de vista (WKWebViewController) que está incrustado en un controlador de navegación. Este ViewController presenta un WKWebView. Después de navegar a cualquier página web; y al presionar durante mucho tiempo cualquier contenido detectado, como un número de teléfono o un enlace, se muestra una hoja de acción con opciones como copiar, compartir, etc. El problema es cuando esta hoja de acción se descarta, el WKWebViewController se descarta junto con él y Se muestra el root ViewController! Independientemente de cuál fue la selección, ya sea Copiar, Cancelar o incluso si se toca en cualquier lugar de la pantalla.

He intentado anular el "presente (_ viewControllerToPresent: UIViewController, indicador animado: Bool, finalización: (() -> Vacío)? = nil)" y el "despedir (bandera animada: Bool, finalización: (() -> Anular)?)"En un intento de comprender lo que está sucediendo, pero luego me di cuenta de que la hoja de acción no se presenta ni se descarta por su controlador de vista principal (WKWebViewController), de hecho, hice lo mismo en el controlador de vista raíz y encontré que no presentado en él tampoco.

He realizado muchas búsquedas para comprender qué está causando este comportamiento, incluso construí un nuevo proyecto solo con un simple WKWebView y siempre terminé con el mismo problema.

Aquí está el código:

import UIKit; import WebKit
class WKWebViewController: UIViewController, WKUIDelegate, WKNavigationDelegate {

var destinationUrlString: String?
var myWebView: WKWebView!

override func viewDidLoad() {
    super.viewDidLoad()

    let webConfiguration = WKWebViewConfiguration()
    webConfiguration.dataDetectorTypes = []
    let origin = CGPoint(x: 0, y: 0)
    let size  = CGSize(width: view.frame.size.width, height: view.frame.size.height)
    myWebView = WKWebView(frame: .init(origin: origin, size: size), configuration: webConfiguration)
    myWebView.uiDelegate = self
    myWebView.navigationDelegate = self
    myWebView.allowsLinkPreview = false
    view = myWebView

    destinationUrlString = "https://www.stackoverflow.com"
    guard let url = URL(string: destinationUrlString!) else {return}
    print(url)
    let request = URLRequest(url: url)
    myWebView.load(request)
}
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
    //show progress indicator
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
    //dismiss progress indicator
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
    //show error
}
func webView(_ webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: Error) {
    //show error
}
}

También adjunté un GIF que muestra el problema:

enter image description here

Estoy usando Xcode 9.3 (9E145) y Swift 4.1.

¿Me estoy perdiendo de algo? ¿Cómo se puede arreglar esto? Cualquier ayuda sería realmente apreciada.


5
2018-04-16 11:49


origen


Respuestas:


He experimentado el mismo problema.

Para hacer frente a esta situación, en el controlador de vista raíz de la UIViewControllerde la jerarquía (en su caso, este será el "Controlador de la vista de raíz"; tenga en cuenta que, en muchos casos, podría ser un UINavgiationController que luego tendrías que subclase) anular dismissViewControllerAnimated:completion: lidiar con el WKWebView llamando a despedir varias veces.

C objetivo

@property (weak) UIViewController *lastPresentedController;

- (void)dismissViewControllerAnimated:(BOOL)flag completion:(void (^)(void))completion
{
    // WKWebView actions sheets workaround
    if (self.presentedViewController && self.lastPresentedController != self.presentedViewController ) {
        self.lastPresentedController = self.presentedViewController;
        [self.presentedViewController dismissViewControllerAnimated:YES completion:^{
            if( completion ) {
                completion();
            }
            self.lastPresentedController = nil;
        }];
    } else if( !self.lastPresentedController) {
        [super dismissViewControllerAnimated:flag completion:completion];
    }
}

Rápido

private weak var lastPresentedController : UIViewController?

override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
    // WKWebView actions sheets workaround
    if presentedViewController != nil && lastPresentedController != presentedViewController  {
        lastPresentedController = presentedViewController;
        presentedViewController?.dismiss(animated: flag, completion: {
            completion?();
            self.lastPresentedController = nil;
        });

    } else if lastPresentedController == nil {
        super.dismiss(animated: flag, completion: completion);
    }
}

6
2018-06-14 12:38



Esto tiene que ser un error. Si anulas despedir en su viewController que contiene la vista web, se llamará cuando el usuario seleccione cualquier acción de la hoja de acción. Si coloca un punto de interrupción en su anulación de descarte, puede ver que el ViewViewController presentado es del tipo WKActionSheet que es una clase interna. Probablemente llamen a despedir para cerrar la hoja de acción, que luego se filtra y descarta nuestro controlador de vista que aloja la vista web. Puede regresar desde dentro de esa función para evitar el cierre, pero luego la acción que eligieron tampoco sucede.

Si no quieres archivar un radar, avísame y lo haré.


1
2018-04-25 18:55