1

I am writing a reusable UIWebView controller and want to descend from that while using the delegate shouldStartLoadWith function and override it as well but I'm not sure how to do it.

In my reusable UiWebView controller I have this.

func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {

    let docURLStr = request.mainDocumentURL!.absoluteString

    if docURLStr.contains("login") {
       loadLoginView()
        return false
    }

Then in my child class I want to do the following but I want to use both functions.How can I do that?

override func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {

let docUrl = request.url!.absoluteString

if String(describing: docUrl).range(of: "some string in the url") != nil{
     return true
     } else {
       return false
       }
}
markhorrocks
  • 1,199
  • 19
  • 82
  • 151

1 Answers1

1

You could simply use the super implementation and combine the two using a logical or or and, depending on what you want to achieve:

override func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool
{
    let docUrl = request.url!.absoluteString
    let load = String(describing: docUrl).range(of: "some string in the url") != nil
    return load || super.webView(webView, shouldStartLoadWith: request, navigationType: navigationType)
}

To check for several strings you might do something like this:

override func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool
{
    let docUrl = request.url!.absoluteString
    let superWantsToLoad = super.webView(webView, shouldStartLoadWith: request, navigationType: navigationType)
    let strings = ["foo", "bar"]
    return superWantsToLoad || strings.contains(where: { docUrl.contains($0) })
}

Please note that the string.contains() call will only be evaluated if superWantsToLoad is false thanks to short-circuit evaluation. This could be important if you have many strings to handle. (Alternatively, you could insert an early return true.)

thm
  • 1,217
  • 10
  • 12
  • I need my super to take precedence over the child which may test for many strings. Specifically, it needs to check for a login link in the loaded web view. – markhorrocks Mar 16 '17 at 18:04
  • To make your super take precedence, can't you simply say `return super.webView(...) || load`? – thm Mar 16 '17 at 18:08
  • Ok, for many string tests I could just create load as a var and then do as you suggest? – markhorrocks Mar 16 '17 at 18:10
  • If every check looks like this one you could also have an array of strings you check against so that you don't need to duplicate code. – thm Mar 16 '17 at 18:14
  • Something along the lines of `return super.(...) || (["foo", "bar"].contains(where: { docUrl.contains($0) }))` – thm Mar 16 '17 at 18:22
  • 1
    I just added example code for multiple strings to the answer to make this more readable. – thm Mar 16 '17 at 18:34
  • My super function may return either true or false as it evaluates some strings and header keys so I don't think this solution will work for me. – markhorrocks Mar 16 '17 at 19:17
  • 1
    If super returns true, then the page will load. If it returns false, your subclass will decide if the page will load. If you don't want to load the page when super returns false, use a logical and instead of an or: `return superWantsToLoad && ...`. Or am I misunderstanding you? – thm Mar 16 '17 at 19:23