Theo Strauss
Theo Strauss

Reputation: 1351

Use JavaScript with UIWebView to retrieve element by ID- SWIFT

I am using a UIWebView to load a webpage that is an article. Once I press a button, I create a struct with the url, title, and image. To access the title, I need to access the webpage's source code and grab the title from a h1 header that has the same class ID (class="c-page-title") for every article. Would anyone know how to use the stringByEvaluatingJavaScript or evaluateJavaScript function to get the text from the h1 header?

Here is some of my code for reference:

Struct:

struct Article {

    var url: URL
    var img: URL
    var title: String

    init(url: URL, img: URL, title: String) {
        self.url = url
        self.img = img
        self.title = title
    }
}

Function that fills the Article struct:

    @IBAction func bookmarkArt(_ sender: Any) {

    let articleInst = Article(url: (mainWebView.request?.url)!, img: (mainWebView.request?.url)!, title: "Article Here")
    bookmarks.append(articleInst)
    print("array: \(bookmarks)")

    let alertController = UIAlertController(title: "Bookmark added!", message: "This article was just added to your bookmarks.", preferredStyle: UIAlertControllerStyle.alert)

    // Replace UIAlertActionStyle.Default by UIAlertActionStyle.default
    let okAction = UIAlertAction(title: "Awesome, thanks!", style: UIAlertActionStyle.default) {
        (result : UIAlertAction) -> Void in
        print("OK")
    }

    alertController.addAction(okAction)
    self.present(alertController, animated: true, completion: nil)
}

Any help would be immensely appreciated!! Thanks so much in advance.

Cheers, Theo

Upvotes: 1

Views: 5393

Answers (1)

Jacob Boyd
Jacob Boyd

Reputation: 690

Sure you can use func stringByEvaluatingJavaScript(from script: String) -> String?

articleInst.title = webView.stringByEvaluatingJavaScript("document.getElementsByClassName(\"c-page-title\")[0].innerHtml;")

The return value will be the html inside of the first element with the class name of "c-page-title".

However, I think a better approach would be the changing your UIWebView into a WKWebView. This will give your javascript a performance boost, if you are running lots of scripts inside your webView from your iOS code. I would also change that "c-page-title" from a class, into a ID, and make sure only one exists on a page. You could then usefunc evaluateJavaScript(_ javaScriptString: String, completionHandler: ((Any?, Error?) -> Void)? = nil) which is much better imo.

So it would look like:

webView.evaluateJavaScript("document.getElementById(\"c-page-title\").innerHtml;") {(response, error) in 
    if (response != nil) { 
        articleInst.title = response as! String
    }
    // error handling
}

Also keep in mind that this is using a complete handler, it is async, so you will need to build your logic for that.

Upvotes: 3

Related Questions