UIWebView: ics and vcard-Links are not processed
I have UIWebView
one that includes a generic URL; unfortunately vcard and ical-Links are not processed, i.e. nothing happens when i click on them.
I tried to install all the data detectors, unfortunately it fails.
In Xcode-log, I get this here when I click on a link like this:
2017-07-14 13:43:00.982413+0200 xxx[2208:967973] WF: _userSettingsForUser mobile: {
filterBlacklist = (
);
filterWhitelist = (
);
restrictWeb = 1;
useContentFilter = 0;
useContentFilterOverrides = 0;
whitelistEnabled = 0;
}
The same stuff works as expected in Safari.
If I use UIApplication.shared.openURL(icsOrVcardUrl)
Safari opens and from there everything works as expected, but I don't want the user to leave the app ...
EDIT This also doesn't work:
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
}
source to share
Use UIDocumentInteractionController to preview without leaving the app. I quickly tested it with an .ics file and it works great.
Implement the protocol UIDocumentInteractionControllerDelegate
extension MainViewController: UIDocumentInteractionControllerDelegate {
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
return self;
}
}
Create an instance of the interaction controller:
let documentController = UIDocumentInteractionController()
Intercept clicks in UIWebView in shouldStartLoadWithRequest
, return false for the links you want to render, with an in-app preview and true for everyone else. Finally:
func previewDocument(_ url: URL) {
documentController.url = url
documentController.presentPreview(animated: true)
}
Here he is in the simulator
EDIT:
In response to a comment on this answer: The reason it doesn't work for you is because it UIDocumentInteractionController
depends on the file extension. Temporary file extension .tmp
Renaming the file after uploading solves the problem. A 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 recommended to clean up after itself because the file will not be deleted after the task completes, although the OS will eventually delete it when space is needed. If you access the same URLs frequently, there Library/Caches/
might be a better place for these files, just come up with the correct naming scheme and check if the file doesn't already exist.
source to share