How to get a string of text like this:
Simple Text Example...
from macOS' Safari page via Swift 4?
#IBOutlet weak var label: NSTextField!
#IBOutlet weak var webView: WKWebView!
override func viewDidLoad() {
super.viewDidLoad()
let string = "http://127.0.0.1:8080/101"
let url = NSURL(string: string)
let request = URLRequest(url: url! as URL)
self.webView.load(request as URLRequest)
//this doesn't work
label.stringValue = webView.webFrame.frameElement.innerText
}
Here is HTML structure:
<html>
<head></head>
<body>
Simple Text Example...
</body>
</html>
UPDATE:
I've tried the following method but it has Void return...
webView.evaluateJavaScript("document.body.innerText") { (result, error) in
if error != nil {
print(result)
}
}
for iOS, in the webview's delegate method
func webViewDidFinishLoad(_ webView: UIWebView) {
var string = webView.stringByEvaluatingJavaScript(from: "document.body.textContent")
print(string)
}
for macOS, in the webview's navigation delegate:
override func viewDidLoad() {
webview.nagivationDelegate = self
...
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.body.textContent") { (string, error) in
print(string)
}
}
You have to check outerhtml and innerhtml, textContent and many more tag like that:
if let htmlOuter = self.webView.stringByEvaluatingJavaScript(from: "document.body.outerHTML"){
}
Or
if let htmlInner = self.webView.stringByEvaluatingJavaScript(from: "document.body.innerHTML"){
}
Or
if let content = self.webView.stringByEvaluatingJavaScript(from: "document.body. textContent"){
}
Related
I'm doing a dictionary application. Some terms have animation, some don't. If ;
let url = URL(string: "http://bsstech.site/-Sozlukler/Fizik/(f.animasyonAdi ?? "").html")!
webview.load(URLRequest(url: url))
or let url = URL(string: "http://bsstech.site/-Sozlukler/Fizik/logo.html")!
webview.load(URLRequest(url: url)) I want to run.
Did I write the code as below, but I did not get the result I wanted.
if let f = fizik {
if (f.animasyonAdi != nil) {
let url = URL(string: "http://bsstech.site/-Sozlukler/Fizik/\(f.animasyonAdi ?? "").html")!
webview.load(URLRequest(url: url))
}else {
let url = URL(string: "http://bsstech.site/-Sozlukler/Fizik/logo.html")!
webview.load(URLRequest(url: url))
}
navigationItem.title = f.baslik
aciklama.text = f.aciklama
}
}
I would be very glad if you help.
Step 1: Create a WebViewViewController
Step 2: Added WebKitView, top title label, a cross button and activity IndicatorView in the WebViewVC.xib file, then insert outlets in the WebViewVC.swift
Step 3: Implement logic in the WebViewVC.swift like the following:
import UIKit
import WebKit
class WebViewVC: UIViewController {
// MARK: - Outlets
#IBOutlet private weak var webView: WKWebView!
#IBOutlet private weak var activityIndicatorView: UIActivityIndicatorView!
#IBOutlet private weak var titleLabel: UILabel!
// MARK: - Variables
private let userAgentValue = "Mozilla/5.0 (iPhone; U; CPU iPhone OS 3_0 like Mac OS X; en-us) AppleWebKit/528.18 (KHTML, like Gecko) Version/4.0 Mobile/7A341 Safari/528.16"
var navTitle: String?
var urlString: String?
// MARK: - View Cycle
override func viewDidLoad() {
super.viewDidLoad()
initView()
setupWebView()
loadData()
}
// MARK: - Event
#IBAction private func actionTapToCloseButton(_ sender: Any) {
dismiss(animated: true, completion: nil)
}
}
// MARK: - Setting up View Controller
extension WebViewVC {
private func initView() {
titleLabel.text = navTitle
}
private func setupWebView() {
webView.navigationDelegate = self
webView.customUserAgent = userAgentValue
webView.isMultipleTouchEnabled = true
webView.isUserInteractionEnabled = true
}
private func loadData() {
if let `urlString` = urlString, !urlString.isEmpty, let query = urlString.addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed), let url = URL(string: query) {
let request = URLRequest(url: url)
webView.load(request)
}
}
}
// MARK: - WKNavigationDelegate
extension WebViewVC: WKNavigationDelegate {
func webView(_ webView: WKWebView, didStartProvisionalNavigation navigation: WKNavigation!) {
activityIndicatorView.startAnimating()
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
activityIndicatorView.stopAnimating()
}
func webView(_ webView: WKWebView, didFail navigation: WKNavigation!, withError error: Error) {
ShowPopUps.showDefaultAlert(title: "", message: "\(error.localizedDescription)", negativeActionText: "Ok")
activityIndicatorView.stopAnimating()
}
}
Step 4: Just Call
if let f = fizik {
var urlString: String? = nil
if (f.animasyonAdi != nil) {
urlString = http://bsstech.site/-Sozlukler/Fizik/\(f.animasyonAdi ?? "").html"
} else {
urlString = "http://bsstech.site/-Sozlukler/Fizik/logo.html"
}
let vc = WebViewVC()
vc.urlString = urlString
vc.navTitle = f.baslik
present(vc, animated: true, completion: nil)
}
I've got a URL and I'm trying to get the HTML content of the site the following way:
func getHtml(_ urlString: String) -> String? {
guard let url = URL(string: urlString) else {
return nil
}
do {
let html = try String(contentsOf: url, encoding: .ascii)
return html
} catch let error {
print("Error: \(error)")
return nil
}
}
if let html = getHtml("https://m.youtube.com/") {
print(html)
}
My issue is, that this gets me the html of the desktop version of the site, however I need the html of the mobile version.
I'm not looking for a workaround for this specific site, but for a general solution, so that, given any URL of a mobile site, it doesn't default to getting me the html of the desktop site.
If you use Viewcontroller in iOS to get the HTML, you can use hidden WKWebView as an alternative and implement the WKNavigationDelegate which has the didFinish method where you can use webView.evaluateJavaScript. As wkwebview is loading from mobile, you will get the mobile version html. Here is the sample of the code.
import UIKit
import WebKit
class YourViewController: UIViewController, WKNavigationDelegate {
let webView = WKWebView()
override func viewDidLoad() {
super.viewDidLoad()
}
#IBAction func BtnClicked(_ sender: Any) {
loadWeb(url: "https://m.youtube.com/")
}
func loadWeb(url: String) {
if let myURL = URL(string: url) {
let request = URLRequest(url: myURL)
webView.navigationDelegate = self
webView.load(request)
}
}
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
webView.evaluateJavaScript("document.documentElement.outerHTML") { (data, error) in
//use html data
print("data", data, error.debugDescription)
}
}
}
I want to disable copying text of my html file that is displayed in a WebKit View. Here is my WebKit View code:
#IBOutlet weak var webView: WKWebView!
#IBOutlet weak var backgroundView: UIView!
var index = 0
var fileName = ""
override func viewDidLoad() {
super.viewDidLoad()
loadSubject()
// Load the appropriate file
let htmlPath = Bundle.main.path(forResource: fileName, ofType: "htm")
let url = URL(fileURLWithPath: htmlPath!)
let request = URLRequest(url: url)
webView.load(request)
}
I'm trying to find a solution and here's the closest one, but I'm not sure how to implement this if it is even the correct answer for me: Prevent user from copying text on browsers
I've been using Swift and Xcode for about 6 months, but I'm brand new to HTML and WebKit View, so I apologize if this is something simple.
Thanks!
try this code
func webViewDidFinishLoad(_ webView: UIWebView) {
webView.stringByEvaluatingJavaScript(from: "document.documentElement.style.webkitTouchCallout='none';")
}
override func canPerformAction(_ action: Selector, withSender sender: Any?) -> Bool {
if action == Selector("customMethod:") {
return super.canPerformAction(action, withSender: sender)
}
return false
}
I am having trouble posting the outputs to a label. I have to covert it to a String? The error it seems to give me is "Cannot subscript a value of type JiNode? with an index of type 'Int'" Please help!
var meter = ""
#IBAction func calculate(sender: AnyObject) {
print("start scraping...")
dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_DEFAULT, 0)) {
let url = NSURL(string: "http://uberestimate.com/costs.php")
let jiDoc = Ji(htmlURL: url!)
if jiDoc != nil {
print("html retrived.\n")
self.scrapeHTML(jiDoc!)
}
}
}
#IBOutlet weak var resultLabel: UILabel!
#IBOutlet weak var endingPoint: UITextField!
#IBOutlet weak var startingpoint: UITextField!
override func viewDidLoad() {
super.viewDidLoad()
// Do any additional setup after loading the view, typically from a nib.
}
override func didReceiveMemoryWarning() {
super.didReceiveMemoryWarning()
// Dispose of any resources that can be recreated.
}
private func scrapeHTML(jiDoc: Ji) {
println("parsing...\n")
let bodyNode = jiDoc.xPath("//body")!.first!
var contentDivNode = bodyNode.xPath("//span[#style='font-size:1.3em']").first
if contentDivNode == nil {
print("unexpected format!")
}else{
var cdnArray = contentDivNode[1]
var cdn = cdnArray[0]! as String
self.resultLabel.text = cdn
// println(contentDivNode)
}
return
}
}
You can do something like:
#IBAction func calculate(sender: AnyObject) {
print("start scraping...")
let url = NSURL(string: "http://uberestimate.com/costs.php")
let task = NSURLSession.sharedSession().dataTaskWithURL(url!) { data, response, error in
if data == nil || error != nil { // in Swift 2, I'd use `guard`, but I tried to keep this backward compatible
print(error)
return
}
dispatch_async(dispatch_get_main_queue()) {
self.scrapeHTML(data!)
}
}
task.resume()
}
private func scrapeHTML(data: NSData) {
print("parsing...\n")
let jiDoc = Ji(data: data, isXML: false)
if let contentDivNode = jiDoc?.xPath("//span[#style='font-size:1.3em']")?.first {
self.resultLabel.text = contentDivNode.content
}
}
I'm using the Swift 2.1 (and I infer from the presence of println that you must be using an earlier version), but I think this is largely the same regardless of Swift version.
BTW, notice that I am dispatching the update of the label back to the main queue (as you called scrapeHTML from a global queue, but UI updates must happen on the main thread). I'm also using NSURLSession rather than dispatching a synchronous network request to a global queue.
I have a UIWebView containing html-formatted text. In the text some words are links. When clicked on they should push another view on to the stack. How should I write the html link and corresponding objective-c code to make this work?
Set up delegate for UIWebView, then you can handle link action clicked:
-(BOOL) webView:(UIWebView *)inWeb shouldStartLoadWithRequest:(NSURLRequest *)inRequest navigationType:(UIWebViewNavigationType)inType {
if ( inType == UIWebViewNavigationTypeLinkClicked ) {
[self.navigationController pushViewController:vc animated:YES];
return NO;
}
return YES;
}
Swift 3: Full UIWebView example to push a view in stack and open another html file in bundle when clicked on html link e.g. imprint
class WebViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
var filename:String?
override func viewDidLoad() {
super.viewDidLoad()
guard filename != nil else {
fatalError("filename not defined")
}
view.backgroundColor = UIColor.white
webView.isOpaque = false;
webView.delegate = self
webView.backgroundColor = UIColor.clear
//remove file extension first
filename = filename!.replace(".html", replacement: "")
let localfilePath = Bundle.main.url(forResource: filename, withExtension: "html")
let myRequest = NSURLRequest(url: localfilePath!)
webView.loadRequest(myRequest as URLRequest)
}
...
}
extension WebViewController: UIWebViewDelegate {
func webViewDidFinishLoad(_ webView: UIWebView) {
//set view title from html document
let pageTitle = webView.stringByEvaluatingJavaScript(from: "document.title")
navigationItem.title = pageTitle
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == .linkClicked,
let urlStr = request.url?.absoluteString,
!urlStr.contains("http://"),
let filename = request.url?.lastPathComponent, //e.g. imprint.html
let vc = storyboard?.instantiateViewController(withIdentifier: "WebView") as? WebViewController{
vc.filename = filename
self.navigationController?.pushViewController(vc, animated: true)
return false
}
return true
}
}