I do have a UIWebView
included where a public URL is loaded; unfortunately, vcard and ical-Links are not handled, i.e. nothing happens when I click on them.
I tried to set all data detectors, no luck unfortunately.
In the Xcode-log, I get this here when clicking on such a link:
2017-07-14 13:43:00.982413+0200 xxx[2208:967973] WF: _userSettingsForUser mobile: {
filterBlacklist = (
);
filterWhitelist = (
);
restrictWeb = 1;
useContentFilter = 0;
useContentFilterOverrides = 0;
whitelistEnabled = 0;
}
In Safari, the same stuff works as expected.
If I use UIApplication.shared.openURL(icsOrVcardUrl)
Safari gets opened and from there everything works as expected again, but I don't want the user to leave the app...
EDIT This doesn't work either:
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if let url = request.url {
if url.absoluteString.contains("=vcard&") || url.absoluteString.contains("/ical/") {
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:url)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
DispatchQueue.main.async {
self.documentController.url = tempLocalUrl
self.documentController.presentPreview(animated: true)
}
}
}
task.resume()
return false
}
}
return true
}
Use a UIDocumentInteractionController to preview without leaving your app. I tested it quickly with an .ics file and it works fine.
Implement the UIDocumentInteractionControllerDelegate
protocol
extension MainViewController: UIDocumentInteractionControllerDelegate {
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self;
}
}
Create an instance of the interaction controller:
let documentController = UIDocumentInteractionController()
Intercept the clicks in your UIWebView in shouldStartLoadWithRequest
, return false for links you want to handle with the in-app preview and true for all the rest. And finally:
func previewDocument(_ url: URL) {
documentController.url = url
documentController.presentPreview(animated: true)
}
Here it is in the simulator
EDIT:
In response to the comment to this answer:
The reason it doesn't work for you is because the UIDocumentInteractionController
depends on the file extension. The extension of the temp file is .tmp
Renaming the file after the download solves the problem. Quick and dirty example:
let task = session.downloadTask(with: url!) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
do {
let filemgr = FileManager.default
let newUrl = tempLocalUrl.appendingPathExtension("ics")
try filemgr.moveItem(at: tempLocalUrl, to: newUrl)
DispatchQueue.main.async {
self.documentController.url = newUrl
self.documentController.presentPreview(animated: true)
}
} catch let error {
print("Error!!!: \(error.localizedDescription)")
}
}
}
task.resume()
In this case it is advisable to clean after yourself, because the file won't be deleted after the task completes although the OS will delete it eventually, when space is needed. If you often access the same urls, Library/Caches/
may be a better place for this files, just come up with good naming schema, and check if the file doesn't exist already.
If you love us? You can donate to us via Paypal or buy me a coffee so we can maintain and grow! Thank you!
Donate Us With