2016-01-09 15 views
9

W mojej aplikacji na iOS napisanej w Swift 2.1 używam WKWebView do załadowania łańcucha HTML, który jest ładowany z blogu wordpress przy użyciu parsera JSON.Linki w WKWebView losowo nieklikalne

Wdrożyłem metodę delegowania func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: (WKNavigationActionPolicy) -> Void) { i ustawiłem delegata nawigacji WKWebView na siebie w celu obsługi linków.

Teraz, kiedy otwieram ViewController, który zawiera WKWebView, ta metoda delegata jest wywoływana raz, co jest zachowaniem, którego można się spodziewać po obciążeniu webView - tak, że delegat wydaje się poprawnie ustawiony.

Mój problem polega na tym, że większość czasu, w którym linki znajdują się w webView, to nie można klikać. Zazwyczaj oczekujesz, że na szarym tle pojawi się , po naciśnięciu linku, jak widać na poniższym obrazku. Ale większość czasu, kiedy naciśniesz łącze, szare tło nie pojawia się, więc gdy się wybiorę, metoda delegatów nie zostanie wywołana. Ten problem z pewnością nie musi działać z błędną konfiguracją WKNavigationDelegate, ponieważ czasami wybór linku działa poprawnie (około 10%).

appearance of links when you select them

Czy masz jakiś pomysł, dlaczego linki nie są losowo czasem klikać, klikać i czasami (10% przypadków)?


+0

Byłoby dobrze, gdyby można było pokazać nam swój html. – adrianokw

+1

Czy zapomniałeś "importować QuartzCore"? –

Odpowiedz

1

Rozwiązaniem jest usunięcie użycia contentInset. Niestety WKWebView nie jest przeznaczone do obsługi korzystanie z niego (gdy contentInset jest ujemna), więc musimy użyć obejście przez proste dodanie pustego div do htmlString, tak po prostu:

<div style='width:100%;height:100px'></div> 

Jeśli dnie wstawkę należy zmienić bez ponownego ładowania całej strony, można najpierw wstawić na dole ogromny div, a następnie zrekompensować go, dodając pozytywną contentInset. To jest dokładnie to, co robi to rozszerzenie:

extension WKWebView { 

    /// The maximum possible height of the webView bottom content inset 
    @nonobjc static let maxBottomHeight: CGFloat = 20000 

    /// Provides an easy way to set the real bottom inset of the webView. Due to a bug in WKWebView framework, we first insert an emtpy div with the size WKWebView.maxContentSize on the bottom of the webView and compensate it by setting a positive contentInset (should be positive, otherwise the bug will be there again). 
    func set(bottomInset inset: CGFloat) { 

     self.scrollView.contentInset.bottom = inset - WKWebView.maxBottomHeight 
    } 
} 

Nie zapomnij dodać div na końcu łańcucha html:

let htmlFooter = "<div style='width:100%;height:\(String(describing: WKWebView.maxBottomHeight))px'></div></body></html>" 
1

podczas ładowania treści do WKWebView, można ustawić złego baseURL na swojej stronie internetowej, a to prowadzi do nieprawidłowego linku, aby mogła ona działa poprawnie, należy mieć swój baseURL rozregulowany http lub https URL dla twoich treści, dla tych pracujących linków tylko dlatego, że mieli pełny adres URL w swoim href.

oto html obciążenie tekst do WKWebView do zilustrowania efektu:

webView.loadHTMLString(content, baseURL: NSURL(string: "")); 

treść:

<html lang="en"><head><meta name="viewport" content="width=device-width, initial-scale=1"></head> 
    <body> 
     <h1> click testing </h1> 
     <ul> 
      <li><a href="http://www.w3schools.com">Visit W3Schools</a></li> 
      <li><a href="/about">Un-Clickable without baseURL</a></li> 
      <li><a href="about://about">Clickable without baseURL</a></li> 
     </ul> 
    </body> 
</html> 
+1

Niestety nie rozwiązuje to mojego problemu, ponieważ ładuję ciąg html do webView, a nie strony internetowej. – fredpi

+1

@returnfalse, oczywiście mówię o twoim html string, to jest zwykły tekst HTML, czy chcesz udostępnić HTML? – Allen

+0

dziękuję za odpowiedź, ale problem polega na tym, że nie mogę otworzyć linków losowo, więc czasami działa określony link, a czasami nie. Jeśli byłby problem z baseURL, zawsze byłby nieklikalny. – fredpi

1

mam zamiar założyć, że to, co chcesz mieć jakiś opis lub tekst w niektórych umieść i pozwól, aby część tekstu była klikalna/klikalna i do tego chcesz użyć WKWebView.

Rozwiązałem ten problem również za pomocą WKWebView w jakiejś aplikacji, którą zrobiłem dawno temu, oczywiście jest kilka rozwiązań, to tylko jeden z nich, nic więcej.

Niektórzy ludzie mówią, że możesz użyć funkcji loadHTMLString, aby załadować ciąg znaków HTML z serwera w JSON lub tak, jak chcesz, ale bardzo ważne jest, aby kod HTML był poprawnie sformatowany bez błędów.

Bardzo ważnym punktem o funkcji loadHTMLString odnośnie Twojego komentarza ... Można by się spodziewać, że zazwyczaj aa szarym tle pojawia się po prasę link jak widać na obrazku poniżej, to nie stanie, jeśli HTML nie ma stylu CSS, ponieważ nie ma domyślnego stylu żadnego z <a><\a>.

Zobaczmy więc następujący kod:

import UIKit 
import WebKit 

class ViewController: UIViewController, WKNavigationDelegate { 

    var wkWebView: WKWebView! 

    override func viewDidLoad() { 
     super.viewDidLoad() 

     // The part of the HTMl you want to show 
     let description = "Let's start to visit the <a href=\"http://www.apple.com/\">Apple</a> website first and then if you want the <a href=\"http://www.w3schools.com\">Developer Apple</a> website." 


     // The default HTML with body and styles formatted and the description inside using string interpolation. 
     let htmlString = "<html><head><style type=\"text/css\">body {font-family: \"Lato-Regular\";font-size: 35px;color: #333333;margin: 0;}a {text-decoration: none; color: #999;}</style></head><body>\(description)</body></html>" 

     let preferences = WKPreferences() 
     preferences.javaScriptEnabled = false 

     // Configuration for any preferences you want to set 
     let configuration = WKWebViewConfiguration() 
     configuration.preferences = preferences 

     wkWebView = WKWebView(frame: CGRectMake(5, 35, self.view.bounds.width, self.view.bounds.height), configuration: configuration) 

     if let theWebView = wkWebView { 
      theWebView.loadHTMLString(htmlString, baseURL: NSURL()) 
      theWebView.navigationDelegate = self 
      self.view.addSubview(theWebView) 
     } 
    } 

    override func didReceiveMemoryWarning() { 
     super.didReceiveMemoryWarning() 
     // Dispose of any resources that can be recreated. 
    } 

    func webView(webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) { 
     UIApplication.sharedApplication().networkActivityIndicatorVisible = true 
    } 


    func webView(webView: WKWebView, didFinishNavigation navigation: WKNavigation!) { 
     UIApplication.sharedApplication().networkActivityIndicatorVisible = false 
    } 

    func webView(webView: WKWebView, didFailProvisionalNavigation navigation: WKNavigation!, withError error: NSError) { 
    let alert = UIAlertController(title: "Error", message: error.localizedDescription, preferredStyle: .Alert) 
    alert.addAction(UIAlertAction(title: "Ok", style: .Default) { (UIAlertAction) -> Void in 
     UIApplication.sharedApplication().networkActivityIndicatorVisible = false 
    }) 

    presentViewController(alert, animated: true, completion: nil) 
    } 
} 

W powyższym kodzie ustawić zmienną description z jakiegoś tekstu z klikalne elementy wewnątrz niego i dodał dwóch metod delegata didStartProvisionalNavigation i didFinishNavigation pokazać networkActivityIndicatorVisible w paski stanu, pokazujące pewien postęp w ładowaniu strony, gdy klikalny tekst jest klikany. Warto zauważyć, że w zmiennej htmlString ustawiam kilka stylów, aby pokazać kolor i czcionkę <a>. To zależy od Ciebie.

Dodałem też funkcję didFailProvisionalNavigation pokazać alert w niektórych przypadkach adres URL jest nieprawidłowy czegoś podobnego nowego HTTPTransportSecurityLayer dodanej jest iOS 9, aby umożliwić tylko https, w niektórych przypadkach można go używać do sprawdzania poprawności url i znać przyczynę błędu.

Wynik jest następujący tekst w normalnym UIViewController:

enter image description here

I po dotknięciu dowolnego szary tekst url byłyby ładowane wewnątrz samego WKWebView, oczywiście można dostosować to do Otwórz w wewnętrznej przeglądarce, którą wykonujesz lub coś innego, to zależy od Ciebie.

a następnie można zobaczyć wynik od razu, jeśli dotknij Jabłko:

enter image description here

Jeśli zamiast tego dotknij Developer Jabłko można zobaczyć wpisu w działaniu ponieważ http protokołu Wystąpił błąd w urządzeniu HTTPTransportSecurityLayer w systemie iOS 9:

enter image description here

Mam gotowy projekt do przesłania na Github, jeśli go potrzebujesz. Mam nadzieję, że ci to pomoże.

+0

Dzięki za szczegółową odpowiedź, naprawdę to doceniam. Niestety nie rozwiązuje to mojego problemu, ponieważ poprawnie skonfigurowałem WKWebView. – fredpi

+0

Czy możesz udostępnić swój projekt w GitHub? –

+0

return true's answer załatwił sprawę, więc nie potrzebuję dalszej pomocy. Mimo to dziękuję! – fredpi