swift 3 - How to close a page (tab) inside a webview - ios

In a viewcontroller I am using this code to open a local html file
self.webView = WKWebView(frame: webFrame, configuration: config)
self.webView?.uiDelegate = self as? WKUIDelegate
self.webView?.navigationDelegate = self
self.webView?.scrollView.bounces = false
self.container!.addSubview(webView!)
let testUrl: URL! = Bundle.main.url(forResource: "index", withExtension: "html", subdirectory: "assets")
self.webView!.loadFileURL(testUrl, allowingReadAccessTo: testUrl)
Debugging by safari in the menu Developer> Simulator appears the open page (index.html) It happens that every time I leave this viewControler and return is added in the menu Developer> Simulator a new page (index.html, index.html, ...) . I believe that new pages are opened in new tabs
In the function I use to exit this viewController I use this code
self.webView?.removeFromSuperview()
self.container.removeFromSuperview()
The objects are removed but the pages are not, does anyone know how to remove them?

Related

User permission from webViewKit button click

Using swift 4 and IOS 12 ,i am using a webViewKit to load a website. One of the features of the web app is to scan qrcode, i have successfully loaded the website but i am still struggling how to access the device camera to scan qr code, in android everything works fine including this qr code scanner using webView onPermissionRequest method. I have already tried this
Key : Privacy - Camera Usage Description in info.plist
and also adding these lines of codes here AVCaptureDevice.authorizationStatus(for: .video) on url load before pressing the web button to scan qr code. According to our web developer this button press executes a javascript undefined function, but i don't know how to make webViewKit respond to this button click event and the hardest part is that there are no logs or NSLogs to evaluate. I am new to IOS development for about almost a month. Thank you
var WebCodeCamJS = function(element) {
'use strict';
this.Version = {
name: 'WebCodeCamJS',
version: '2.7.0',
author: 'Tóth András',
};
var mediaDevices = window.navigator.mediaDevices;
mediaDevices.getUserMedia = function(c) {
return new Promise(function(y, n) {
(window.navigator.getUserMedia || window.navigator.mozGetUserMedia || window.navigator.webkitGetUserMedia).call(navigator, c, y, n);
});
}
HTMLVideoElement.prototype.streamSrc = ('srcObject' in HTMLVideoElement.prototype) ? function(stream) {
this.srcObject = !!stream ? stream : null;
} : function(stream) {
if (!!stream) {
this.src = (window.URL || window.webkitURL).createObjectURL(stream);
} else {
this.removeAttribute('src');
}
};
Above code is a js function named webcodecamjs.js that is being executed from a button click event on the web page. I found similar problem with solution here , but i'm not quite sure how to implement it, it says
Now Add JS file (WebRTC.js) that defines various WebRTC classes, functions & passes the calls to the WKWebView.
In the WKWebView inject the script at the document start:
where do i put this WebRTC.js file? what i did was to create a new file in my ios project and named it WebRTC.js , i also tried renaming it to webcodecamjs.js like what we have in web js files, how i did it in func viewDidAppear
let contentController = WKUserContentController()
contentController.add(self, name: "callbackHandler")
let script = try! String(contentsOf: Bundle.main.url(forResource: "webcodecamjs", withExtension: "js")!, encoding: String.Encoding.utf8)
contentController.addUserScript(WKUserScript(source: script, injectionTime: WKUserScriptInjectionTime.atDocumentStart, forMainFrameOnly: true))
let preferences = WKPreferences()
preferences.javaScriptEnabled = true
let configuration = WKWebViewConfiguration()
configuration.preferences = preferences
configuration.userContentController = contentController
configuration.allowsPictureInPictureMediaPlayback = true
webView.navigationDelegate = self
webView.configuration.preferences = configuration.preferences
WKWebView.load(webView)(NSURLRequest(url: NSURL(string: encodedLoginUrl)! as URL) as URLRequest)
webView is a
#IBOutlet weak var webView: WKWebView
not declared as below
var webView: WKWebView
that's why i can't do something like below, cause it gives me 'weak' warning
webView = WKWebView(frame: CGRect.zero, configuration: config)
Could you add code snippet to check?

How to load an html file into a webView for multiple targets

Inside my app I have a html credits file which I want to load into a webView. The code I'm using works perfectly fine for my main target. However later on I created a second target: the pro-version of the app but for this one the code doesn't work because url is nil.
Both targets are selected on Target Membership for credits.html
I have tried changing the Location of the file in the identity inspector to all possibilities with no success.
I guess the file is somehow saved with a path only the main target can access.
if let urlPath = Bundle.main.path(forResource: "credits", ofType: "html") {
if let url = URL(string: urlPath) {
webView.loadRequest(URLRequest(url: url))
}
}
You need to use Bundle(identifier:) to get a bundle for a specific target. You can learn the Bundle identifier for each specific target by going to the Build settings of your target and looking at the Product Bundle Identifier variable.
if let targetBundle = Bundle(identifier: "yourBundleId"), let filePath = targetBundle.url(forResource: "credits", withExtension: "html") {
webView.loadRequest(URLRequest(url: url))
}

Preload multiple local WebViews

Because I could just find some outdated information / not working solutions to my problem I decided to ask this kind of question again. (See outdated / wrong solutions:)
WKWebView: Is it possible to preload multiple URLs?
(Xcode, Swift) Is it possible to load multiple WKWebViews simultaneously if they are on different viewControllers?
Swift 3, iOS 10.3 - Preload UIWebView during Launch Screen
My app is separated in one native part and one HTML part. The HTML is saved as a local file (index.html) and should be load into the myWebView view.
#IBOutlet weak var myWebView: UIWebView!
func loadWebview() {
let url = Bundle.main.url(forResource: "index", withExtension: "html")
let request = URLRequest(url: url!)
myWebView.loadRequest(request)
myWebView.scrollView.isScrollEnabled = false
myWebView.allowsLinkPreview = false
myWebView.delegate = self
}
Because my DOM tree is very large, switching from the native part to the web part (on button click) takes quite a long time at -least for the first time switching- because afterward, I'm sure the webView-request gets cached.
To my question: How can I preload the WebView on app init to avoid the white screen (maybe 0.5s - 1s duration) when switching from the native to the Web part?
EDIT:
The WKWebView is displaying the scrollbar while the UIWebView was not!
Using (like with UIWebView) this styles:
::-webkit-scrollbar {
display: none;
}
is not working and adding these lines:
webview.scrollView.showsHorizontalScrollIndicator = false
webview.scrollView.showsVerticalScrollIndicator = false
is also not working at all.
Firstly, you should switch to WKWebView,UIWebView is no longer recommended to be used by Apple.
Secondly, you can create a pool of web views that get created and asked to load when the app starts. This way by the time the user switches to the web interface the web view might've got a chance to fully load.
For this you can use a class like this:
/// Keeps a cache of webviews and starts loading them the first time they are queried
class WebViewPreloader {
var webviews = [URL: WKWebView]()
/// Registers a web view for preloading. If an webview for that URL already
/// exists, the web view reloads the request
///
/// - Parameter url: the URL to preload
func preload(url: URL) {
webview(for: url).load(URLRequest(url: url))
}
/// Creates or returns an already cached webview for the given URL.
/// If the webview doesn't exist, it gets created and asked to load the URL
///
/// - Parameter url: the URL to prefecth
/// - Returns: a new or existing web view
func webview(for url: URL) -> WKWebView {
if let cachedWebView = webviews[url] { return cachedWebView }
let webview = WKWebView(frame: .zero)
webview.load(URLRequest(url: url))
webviews[url] = webview
return webview
}
}
and ask it to preload the url sometimes during the app startup:
// extension added for convenience, as we'll use the index url in at least
// two places
extension Bundle {
var indexURL: URL { return self.url(forResource: "index", withExtension: "html")! }
}
webviewPreloader.preload(url: Bundle.main.indexURL)
Thirdly, you might need to use a container view instead of the actual web view, in your controller:
#IBOutlet weak var webviewContainer: UIView!
What remains is to add the preloaded web view to the container when needed:
func loadWebview() {
// retrieve the preloaded web view, add it to the container
let webview = webviewPreloader.webview(for: Bundle.main.indexURL)
webview.frame = webviewContainer.bounds
webview.translatesAutoresizingMaskIntoConstraints = true
webview.autoresizingMask = [.flexibleWidth, .flexibleHeight]
webviewContainer.addSubview(webview)
}
And not lastly, be aware that keeping alive instances of web views, might carry performance penalties - memory and CPU-wise.

WebView (not WKWebView) calling Localized HTML file

A Mac app requires that a HTML file be called in a WebView (the legacy type, not the newer WKWebView) in a localized form to present the user with some content.
As I side note, I realize that WebView should not be used today, and WKWebView is preferred, however this is a legacy app that currently needs support.
I've used a similar method for the iOS version, however it does not seem to be working. The HTML files are simply called "Term.HTML" and are placed in each localization folder alongside the localized string and all other localized content. This is the code I tried to use:
NSString *htmlFile = [[NSBundle mainBundle] pathForResource:NSLocalizedString(#"fileTerm", nil) ofType:#"html"];
htmlString = [NSString stringWithContentsOfFile:htmlFile encoding:NSUTF8StringEncoding error:nil];
[termsView takeStringURLFrom:htmlString];
Where my localized strings file each contain a line that says:
"fileTerm" = "Term";
This is what links the declaration of the first line to the actual file. It works in iOS. However, when running the app and the view containing the WebView attempt to the run, XCode will automatically create a breakpoint on the third line when I actually attempt to give the HTML file to "termsView" which is my WebView. After skipping this breakpoint, and forcing the app to run, the whole view containing the WebView will simply not appear. I would be thankful if anyone knew why this was or if there was a better way to do this? Thank you everyone!
may be someone needs in SWift: I solved this problem with saving 3 html file for every language, and then in ViewController class checked current app language. And called up the html file for current language
func loadHtmlFile() {
let preferredLanguage = NSLocale.preferredLanguages[0]
if preferredLanguage == "kz" {
let url = Bundle.main.url(forResource: "aboutUs_kz", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
if preferredLanguage == "ru" {
let url = Bundle.main.url(forResource: "aboutUs_ru", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
if preferredLanguage == "en" {
let url = Bundle.main.url(forResource: "aboutUs_en", withExtension:"html")
let request = URLRequest(url: url!)
webView.load(request)
}
}
in viewDidLoad()
override func viewDidLoad() {
super.viewDidLoad()
loadHtmlFile()
}

Open some items in UIWebView, and others in external browser

I'm creating a html5 app, embed in UIWebView. I have delegate webview to controller, and on shouldStartLoadWithRequest, I'm looking for url pattern to open or not on external browser.
It's work perfect!
But when phone has no connection, I'm loading local html file. Because shouldStartLoadWithRequest return FALSE on first request, offline.html not loading
Anyone has do that?
Try this immediately after set path :
do {
let path = NSBundle.mainBundle().pathForResource("offline", ofType: "html", inDirectory:"offline")
let string = try String(contentsOfFile: path!, encoding:NSUTF8StringEncoding)
webView.loadHTMLString(string, baseURL: NSURL(string: "http://"))
} catch {
print(error)
}
or
let url = NSURL(fileURLWithPath:NSBundle.mainBundle().pathForResource("offline", ofType:"html", inDirectory: "offline")!)
let request = NSURLRequest(URL: url);
webView.loadRequest(request);
I tried it and it works.
Make sure your "offline" directory is a folder (BLUE) and not a group (YELLOW).
Hope this help.
I found the problem. I'm not triggering error -1003 (no host found)! removing switch work perfectly!

Resources