I am trying to load a html which has 2 frames in it using WKWebView. I am getting all the navigation delegates for main frame once but not getting didCommit and didFinish callback for subframes.
My sample html is like this:
https://example.com <html><head><base href="https://example.com"></head><frameset framespacing="0" rows="*,0" frameborder="0" noresize><frame name="sco" src="https://example.com//assets/s/uruq3acajh9u/x/mobile/path/loading.html"><frame name="adaptor" src="https://example.com//assets/s/uruq3acajh9u/content/mobile/path/1.html?sco_url=https://example.com/content/elearningngx/VHDRczdEy5kO_pRfKsNJEA/1571433806/0088Z2lPcUR4MVljWWlPUVYvSjNrby9OVjJzbk84OENkN1h3SVl3UVBPMG9sb3lXNFFsaHUwT2xDbVhFTzVpMWdiNQ==RnJpIE9jdCAxOCAxMzoyMzoyNiBVVEMgMjAxOQ==/eot/index.html"></frameset></html>
func setupWebView(){
if (self.webView != nil){
self.webView.removeFromSuperview()
}
HTTPCookieStorage.shared.cookieAcceptPolicy = .always
let userContentController = WKUserContentController()
userContentController.addUserScript(HTMLViewScripts.viewportScript)
let pref = WKPreferences()
pref.javaScriptEnabled = true
pref.javaScriptCanOpenWindowsAutomatically = true
pref.setValue(true, forKey: "allowFileAccessFromFileURLs")
pref.setValue(true, forKey: "_allowUniversalAccessFromFileURLs")
let wkWebConfig = WKWebViewConfiguration()
wkWebConfig.preferences = pref
wkWebConfig.userContentController = userContentController
let wkWebSiteStore = WKWebsiteDataStore.nonPersistent()
wkWebConfig.websiteDataStore = wkWebSiteStore
self.webView = WKWebView(frame: CGRect(x: 0, y: 0, width: Constants.screenSize.width, height: self.playerContainer.frame.size.height), configuration: wkWebConfig)
self.webView.navigationDelegate = self
self.webView.uiDelegate = self
self.playerContainer.addSubview(self.webView)
}
Also same issue with evaluateJavaScript as well. I am not getting any callback when loading "about:blank" using evaluateJavaScript. Seems same frames related issue.
Any leads would be appriciated. Thanks in advance.
Related
Problem:
I would like to implement a similar solution that WKWebView has but with SFSafariViewController.
allowsInlineMediaPlayback = false
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = false
How can I implement a similar functionality with Safari Services?
import SafariServices
let bookmark = NSURL(string: youtubeVideoURL)
let config = SFSafariViewController.Configuration()
let safari = SFSafariViewController(url: bookmark as! URL)
if(UIDevice.current.userInterfaceIdiom == .pad) {
safari.modalPresentationStyle = .fullScreen
}else{
safari.modalPresentationStyle = .fullScreen
}
self.present(safari, animated: true, completion: nil)
Exactly what I want accomplished is in the code below. However, I am wondering if it can be done with a SFSafariViewController by somehow implementing
allowsInlineMediaPlayback
let youtubeVideoURL = posts[sender.view?.tag ?? 0].youtube_video_url + "?playsinline=1?autoplay=1"
var myPlayer: WKWebView!
let webConfiguration = WKWebViewConfiguration()
webConfiguration.allowsInlineMediaPlayback = false
webConfiguration.mediaTypesRequiringUserActionForPlayback = []
myPlayer = WKWebView(frame: UIScreen.main.bounds, configuration: webConfiguration)
self.view.addSubview(myPlayer)
if let mediaURL:URL = URL(string: youtubeVideoURL) {
let request:URLRequest = URLRequest(url: mediaURL);
myPlayer.load(request)
}
Pseudocode:
let config = SFSafariViewController.Configuration()
config.allowsInlineMediaPlayback = false
I tried implementing the solution in the answer of this question and I couldn't.
I'm trying to trigger an in-app safari browser with a pre-set link from a PDF widget button.
This is my code sample:
import UIKit
import PDFKit
import SafariServices
...
//Safari VC declaration with the desired link
let sfVC = SFSafariViewController(url: URL(string: "https://www.apple.com/")!)
func insertLinkButtonInto(_ page: PDFPage) {
let pageBounds = page.bounds(for: .cropBox)
let linkButtonBounds = CGRect(x: 90, y: pageBounds.size.height - 300, width: 106, height: 32)
let linkButton = PDFAnnotation(bounds: linkButtonBounds, forType: PDFAnnotationSubtype(rawValue: PDFAnnotationSubtype.widget.rawValue), withProperties: nil)
linkButton.widgetFieldType = PDFAnnotationWidgetSubtype(rawValue: PDFAnnotationWidgetSubtype.button.rawValue)
linkButton.widgetControlType = .pushButtonControl
linkButton.caption = "Click link"
page.addAnnotation(linkButton)
let linkButtonAction = PDFActionURL(url: URL(string: "https://www.apple.com/")!)
// linkButtonAction.action = How do I implement the code?
}
This is the action I'm trying to trigger:
present(sfVC, animated: true)
This is the function that I didn't know how to implement:
func pdfViewWillClick(onLink sender: PDFView, with url: URL) {
print(url)
}
This is the code in ViewDidload:
override func viewDidLoad() {
super.viewDidLoad()
if let documentURL = Bundle.main.url(forResource: "PDFFileName", withExtension: "pdf"),
let document = PDFDocument(url: documentURL),
let page = document.page(at: 0) {
// Set our document to the view, center it, and set a background color
pdfView?.document = document
pdfView?.autoScales = true
pdfView?.backgroundColor = UIColor.lightGray
self.insertLinkButtonInto(page)
}
I know the solution might be very easy for an experience programmer. I would really appreciate the help.
You are missing few things in your current code. In your viewDidLoad method set the delegate of the pdfView
override func viewDidLoad() {
super.viewDidLoad()
if let documentURL = Bundle.main.url(forResource: "Application", withExtension: "pdf"),
let document = PDFDocument(url: documentURL),
let page = document.page(at: 0) {
// Set our document to the view, center it, and set a background color
pdfView?.document = document
pdfView?.autoScales = true
pdfView?.backgroundColor = UIColor.lightGray
self.insertLinkButtonInto(page)
//set the delegate of the pdfView to this viewController
pdfView?.delegate = self
}
Present the SFSafariViewController in delegate method with the url
func pdfViewWillClick(onLink sender: PDFView, with url: URL) {
print(url)
let sfVC = SFSafariViewController(url: url)
self.present(sfVC, animated: true)
}
set the action for PDFAnnotation in
func insertLinkButtonInto(_ page: PDFPage) {
let pageBounds = page.bounds(for: .cropBox)
let linkButtonBounds = CGRect(x: 90, y: 10, width: 106, height: 32)
let linkButton = PDFAnnotation(bounds: linkButtonBounds, forType: PDFAnnotationSubtype(rawValue: PDFAnnotationSubtype.widget.rawValue), withProperties: nil)
linkButton.widgetFieldType = PDFAnnotationWidgetSubtype(rawValue: PDFAnnotationWidgetSubtype.button.rawValue)
linkButton.widgetControlType = .pushButtonControl
linkButton.caption = "Click link"
page.addAnnotation(linkButton)
let linkButtonAction = PDFActionURL(url: URL(string: "https://www.apple.com/")!)
//set the linkButton action
linkButton.action = linkButtonAction
}
I need to read value stored in the local storage of WKWbview.
I tried using the below code but getting nil.
I am able to write values in local storage but facing difficulty in reading values from it.
let script = "localStorage.getItem('token')"
wkWebView.evaluateJavaScript(script) { (token, error) in
print("token = \(token)")
}
WKWebView init code:
// 1
let accessToken = UserDefaults.standard.value(forKey: "token") as? String
// 2
let refreshToken = UserDefaults.standard.value(forKey: "RefreshToken") as? String
// 3
let configuration = WKWebViewConfiguration()
// 4
let contentController = WKUserContentController()
let accessTokenScript = "javascript: localStorage.setItem('token', '\(accessToken!)')"
// 5
let userAccessTokenScript = WKUserScript(source: accessTokenScript, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: false)
// 6
contentController.addUserScript(userAccessTokenScript)
configuration.userContentController = contentController
self.wkWebView = WKWebView(frame: controller.view.bounds, configuration: configuration)
You need to inject this script when the website has already loaded:
your WKWebView needs to assign the navigationDelegate
webView.navigationDelegate = self
inject the script when the website was loaded completely
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
//you might want to edit the script, with the escape characters
let script = "localStorage.getItem(\"token\")"
wkWebView.evaluateJavaScript(script) { (token, error) in
if let error = error {
print ("localStorage.getitem('token') failed due to \(error)")
assertionFailure()
}
print("token = \(token)")
}
}
Rather than loading a WebView from a URL like this
override func viewDidLoad() {
super.viewDidLoad()
let url = URL(string: imageUrl.urlString)
let request = URLRequest(url: url!)
webView.load(request)
}
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
How can I load a UIImage onto the WebView in Swift 4?
Try Something like this.
let html = "<html><img src=\"datadb/DestinationGuide/Images/YourImage.png\"/> </html>"
//Save this html in `DocumentDirectory`
let saveHTML = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0].appendingPathComponent("temp.html")
try? html.data(using: .utf8)!.write(to: saveHTML)
//Now load this `temp.html` file in webView
webView.loadRequest(URLRequest(url: saveHTML))
I am having an issue with WKWebView I init like this
let configuration = WKWebViewConfiguration()
configuration.applicationNameForUserAgent = "Browser"
configuration.ignoresViewportScaleLimits = true
configuration.allowsInlineMediaPlayback = true
configuration.allowsAirPlayForMediaPlayback = true
configuration.allowsPictureInPictureMediaPlayback = true
configuration.mediaTypesRequiringUserActionForPlayback = WKAudiovisualMediaTypes.audio
configuration.selectionGranularity = WKSelectionGranularity.character
configuration.dataDetectorTypes = WKDataDetectorTypes.link
let webview = WKWebView(frame: .zero, configuration: configuration)
webview.allowsBackForwardNavigationGestures = true
webview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webview.uiDelegate = self
webview.navigationDelegate = self
let url = URL(string: "https://www.google.com")!
let request = URLRequest(url: url)
webview.load(request)
self.view = webview
everytime I enter a search box on a website for example "Google" I get this log in the debugger... I can't seem to understand why it is throwing constraint issues while I did not set any... and this view is contained in UINavigationController that has a UIToolbar
Screenshot of Storyboard.