go to the previous local html in UIWebView in iOS - html

In my project there are plenty of html files which through anchor links are connected to each other.
All of the html files are shown after selected in a UITableView, by an UIWebView. Once loaded the anchor links work and user can go to the chosen html.
Now the problem arises when want to go back, since whatever i do the back button in the navigation bar takes us to the tableView not the previous html.
How can i add a back button and how do i know that at any given time which html is being seen through UIWebView ?
import UIKit
class DisplayViewController: UIViewController, UIWebViewDelegate {
var articleName = “”
#IBOutlet var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
functionOfWebView()
}
func functionOfWebView()
{
let URL = Bundle.main.url(forResource: "\(articleName)", withExtension: "html")
let request = NSURLRequest(url: URL! as URL)
webView.loadRequest(request as URLRequest)
}

You can easily achieve this by linking the webView's "goBack" action to a UIButton.
I assume that you are navigating between the html files in the same webView.
From the storyboard, select the webView and then select "Connections Inspector":
Note that there is "goBack" option in the list of "Received Actions"; Drag from its circle to a button:
Now, instead of popping the current ViewController, the button should do the desired functionality to your case (back to the previous webpage in the webview).

In my case i did a VC's property isInitialWebPageLoaded which reflects whether or not webView is loaded from HTML string or not - which implicates that user did tap link or something else happened.
To get know when it happened VC need to conform to UIWebViewDelegate protocol and implement func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool like that:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
isInitialWebPageLoaded = navigationType != .linkClicked
return true
}
After that with every back button action is being invoked i simply check:
if webView.canGoBack {
webView.goBack()
} else if isInitialWebPageLoaded == false {
webView.loadHTMLString(yourHTMLString, baseURL: nil)
} else {
navigationController?.popViewController(animated: true)
}
Hope it helped.

You must to add an unique ID in the HTML and later when go back with "goBack" action parse the html finding the ID .

Related

How to open another .html file inside WKWebView when a link gets tapped?

I am using SwiftUI along with UIViewRepresentable to instantiate a WKWebView to display my html content:
WebView
struct WebView : UIViewRepresentable {
let request: URLRequest
func makeUIView(context: Context) -> WKWebView {
return WKWebView()
}
func updateUIView(_ uiView: WKWebView, context: Context) {
uiView.load(self.request)
}
}
SwiftUI View
let localFilePath = Bundle.main.url(forResource: "EULA for ALP app", withExtension: "html")
VStack{
WebView(request: URLRequest(url: localFilePath!))
}.padding([.leading,.trailing],20)
HTML
When I tap the span nothing happens as if its not registering the hit, I want to use another local HTML file like the one I am using inside the WebView so when the span gets tapped the WebView displays the corresponding file. I would also like to mention that HTML gets displayed correctly just without the href working.
<span href="file://practitionerPolicy.html">Tap Me!</span>
I assume in this case, as this is your internal resources, relative path should work, like
<span href="practitionerPolicy.html">Tap Me!</span>

Why is dismissing uinavigationcontroller not releasing view controller memory?

Implementing UIDocumentBrowserViewController in an existing app. This vc, in iOS 11 is the root view controller, and tapping a file creates my doc, instantiates my view controller, and presents it inside a UINavigationController. It all works, in that the files display, the proper document opens, the vc displays and works as expected. I had to add a left button to the nav bar to provide a way to close the doc/vc.
When I tap the "Done" button, the view controller closes and returns to the document browser. All of that is good.
The problem is that the view controller's memory isn't releasing (and the domino effect of document memory, etc then not releasing). In the iOS 10 side of things, with a UICollectionViewController embedded in a UINavigationController as the initial vc, but the doc and the display vc identical code for iOS 10 & 11, all memory releases. I've studied How to correctly dismiss a UINavigationController that's presented as a modal? and related posts, tried dozens of alternatives, and am just not seeing what I'm missing. Instruments isn't showing any memory leaks, though I see document objects in memory after dismissing the view controller. The log shows that the vc's viewWillDisappear is being called at the proper time.
I appreciate any insights into why the vc memory isn't being released (deinit() not being called).
Thank you.
#available(iOS 11.0, *)
class DocumentBrowserViewController: UIDocumentBrowserViewController, UIDocumentBrowserViewControllerDelegate {
override func viewDidLoad() {
super.viewDidLoad()
delegate = self
allowsDocumentCreation = true
allowsPickingMultipleItems = false
}
// MARK: Document Presentation
func returnToDocumentBrowser(sender: UIBarButtonItem) {
print("returnToDocumentBrowser")
if let controller = self.presentedViewController as? UINavigationController {
controller.dismiss(animated: true, completion: nil)
}
}
func presentDocument(at documentURL: URL) {
print("present document")
let doc = MyDocument(fileURL: documentURL)
doc.open(completionHandler: { (success) in
if (success) {
print("open succeeded")
DispatchQueue.main.async {
let myController = self.storyboard!.instantiateViewController(withIdentifier: "my controller") as! MyViewController
myController.navigationItem.setLeftBarButton(UIBarButtonItem(barButtonSystemItem: UIBarButtonSystemItem.done, target: self, action: #selector(self.returnToDocumentBrowser(sender:))), animated: false)
myController.doc = doc
let navigationController = UINavigationController(rootViewController: myController)
self.present(navigationController, animated: true, completion: nil)
}
} else {
print("open failed")
}
})
}
}
The navigation stack seems at the heart of this. In the iOS 10 version, a collection view controller is the root view controller and is embedded in a navigation controller via storyboard.
In the iOS 11 version, the document browser view controller is the root view controller and cannot be embedded in a navigation controller. When I presented in the original code, my document view controller became the navigation stack's root view controller, and that cannot be popped, for example.
So I figured that maybe the navigation controller needed a different root view controller to mimic the prior behavior as much as possible and require the fewest code changes.
So I changed
let navigationController = UINavigationController(rootViewController: myController)
self.present(navigationController, animated: true, completion: nil)
to
let dummyVC = UIViewController()
let navigationController = UINavigationController(rootViewController: dummyVC)
from.present(navigationController, animated: true, completion: nil)
dummyVC.navigationController?.pushViewController(myController, animated: true)
This nav controller setup added a back button, meaning I didn't have to add a back button, and that handled popping the view controller automatically. As a result, I only needed to dismiss the nav controller, since it wasn't the app's root vc.
Finally, for the comment that the delegate should be declared weak, that's Apple's doing, and I just use it as provided. I'm not sure what affect that's having on things.

How to open local html file on Safari?

I want to open a local html file on Safari integration on my Swift 3 application.
I know how to do this with an url. This is the code that I use to do that:
let encodedString = url.addingPercentEncoding(withAllowedCharacters: .urlQueryAllowed)
let svc = SFSafariViewController(url: NSURL(string: encodedString!) as! URL)
self.present(svc, animated: true, completion: nil)
But I am not able to do the same with a local file. I have copied my html file on my project and I can see it on the directories tree but I am not able to make it to work. I have looked at Load local html into UIWebView using swift for reference.
How can I load a local html file into Safari integration?
Thanks in advance!
You can't do it using SFSafariViewController
From Apple Documentation:
1. Choosing the Best Web Viewing Class
If your app lets users view websites from anywhere on the Internet, use the SFSafariViewController class. If your app customizes, interacts with, or controls the display of web content, use the WKWebView class.
2. if you look at declaration of init
convenience init(url URL: URL)
url: The URL to navigate to. The URL must use the http or https scheme.
Using Webkit or WebView
helloAshok.html
<html>
<head>
</head>
<body>
<br />
<h2> Welcome ASHOK</h2>
</body>
</html>
ViewContrller.swift
class ViewController: UIViewController {
#IBOutlet weak var myWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let localFilePath = Bundle.main.url(forResource: "helloAshok", withExtension: "html")
let request = URLRequest(url: localFilePath!)
myWebView.loadRequest(request)
}
}
Output:

iOS: Excluding certain URLs when running webview

I am using Swift and have web-based content (an external webpage) embedded in WebView for my native app. On that webpage, again, which is in-app, I need to make one link open in Safari and not in the App. HTML target _blank code on the webpage doesn’t work (I wish it was that easy), looking for the right code to do it in Swift.
I have used this code for uiwebview:
#IBOutlet var news: UIWebView!
var theURL = "http://"
override func viewDidLoad() {
super.viewDidLoad()
loadWebPage()
}
func loadWebPage(){
let requestURL = NSURL (string: theURL)
let URLrequest = NSURLRequest (URL: requestURL!)
news.loadRequest(URLrequest)
I have used this code for WKNaviagtionDelegate:
func webView(webView: WKWebView, decidePolicyForNavigationAction navigationAction: WKNavigationAction, decisionHandler: ((WKNavigationActionPolicy) -> Void)) {
if (navigationAction.navigationType == WKNavigationType.LinkActivated && !navigationAction.request.URL!.host!.lowercaseString.hasPrefix("http://")) {
UIApplication.sharedApplication().openURL(navigationAction.request.URL!)
decisionHandler(WKNavigationActionPolicy.Cancel)
} else {
decisionHandler(WKNavigationActionPolicy.Allow)
}
Best, Drew
Because you need to create a button that looks like a link.
that should do the trick:
UIApplication.sharedApplication().openURL(NSURL(string: "http://...")!)
If the button is actually on a webpage in WebView... the link is not really controlled by the App unless you manipulate the link in iOS. It looks like the HTML target="_new" tag on the button might work in a later version of iOS. It's a bug in iOS 7 and was fixed in 7.0.3. Try a higher iOS version target for the App with the HTML target tag on the button.
How to open Safari from a WebApp in iOS 7

Trouble sending info between view controllers with modal presentation

I am having trouble sending info from one viewcontroller to the next. In my storyboard I am using a modal presentation. When I write the destinationviewcontroller is when I get the error. If I do not write that line the code works ok. Any ideas?
override func prepareForSegue(segue: UIStoryboardSegue, sender: AnyObject!) {
if (segue.identifier == "segueEditItem") {
// if I erase the next 2 lines the code will run ok
let ss = segue.destinationViewController as EditItemViewController
ss.toPassID = toPassID
}
}
Try out:
let ss = (segue.destinationViewController.visibleViewController as EditItemViewController)
I think you already set in your Storyboard Settings or your segue the presentation to "Modal" ?