I think something changed within Swift that disabled me from previewing my files. It worked fine previously. If I click on say a PDF file in my app, I see the title of the PDF, but the content of PDF (preview) area does not show.
Below is my code & logs & also the screenshot. If anyone has an idea of where I can fix the issue, any help would be greatly appreciated.
// When file is clicked this method is called
#objc private func handleTapped() {
guard let url = self.file.fileUrl else { return }
if self.file.isDownloaded {
self.showDocumentController(url: self.file.urlInDocumentsDirectory! as NSURL)
return
}
SVProgressHUD.showProgress(0)
let destination: DownloadRequest.DownloadFileDestination = { _, _ in
let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
let fileURL = documentsURL.appendingPathComponent("pig.png")
return (documentsURL, [.removePreviousFile, .createIntermediateDirectories])
}
Alamofire.download(url, to: destination)
.downloadProgress { (download) in
DispatchQueue.main.async() {
SVProgressHUD.showProgress(Float(download.fractionCompleted))
}
}.validate(statusCode: 200..<300)
.response { (response) in
SVProgressHUD.dismiss()
guard response.response?.statusCode == 200 else { return }
let directoryURL = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]
let pathURL = URL(fileURLWithPath: directoryURL, isDirectory: true)
//pathURL: file:///var/mobile/Containers/Data/Application/6DDCCC30-107C-4613-B63D-18962C3D06D3/Documents/
guard let fileName = response.response?.suggestedFilename else { return }
//fileName: 05_기조강연_RobertMankin_BETTER+OFFICES+GREATER+INNOVATION.pdf
let fileURL = pathURL.appendingPathComponent(fileName)
//fileURL: file:///var/mobile/Containers/Data/Application/6DDCCC30-107C-4613-B63D-18962C3D06D3/Documents/05_%E1%84%80%E1%85%B5%E1%84%8C%E1%85%A9%E1%84%80%E1%85%A1%E1%86%BC%E1%84%8B%E1%85%A7%E1%86%AB_RobertMankin_BETTER+OFFICES+GREATER+INNOVATION.pdf
self.saveFileURL(url: fileURL as NSURL)
self.showDocumentController(url: fileURL as NSURL)
}
}
private func saveFileURL(url: NSURL) {
self.file.urlInDocumentsDirectory = url as URL
let realm = RealmService.defaultRealm
try! realm?.write {
realm?.add(self.file, update: true)
}
self.file = self.file.copyFromRealm()
}
private func showDocumentController(url: NSURL) {
let docController = UIDocumentInteractionController(url: url as URL)
docController.delegate = self
docController.presentPreview(animated: true)
}
// MARK: UIDocumentInteractionControllerDelegate methods
func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
if let controller = UIApplication.shared.keyWindow?.topMostViewController() {
return controller
}
return UIViewController()
}
this is how the preview shows
Here Is The Code
import UIKit
import Alamofire
class ViewController: UIViewController, UIWebViewDelegate
{
#IBOutlet weak var WebView: UIWebView!
var NewsURL: String = ""
override func viewDidLoad()
{
super.viewDidLoad()
Self.LoadPdf()
}
func LoadPdf()
{
let url = NSURL (string: "\(http://)") //Your Pdf URL Here
let requestObj = NSURLRequest(URL: url!);
WebView.loadRequest(requestObj)
}
}
Related
Given the code below I am successfully downloading my tar.gz file but when I try unzip it I get
Error creating a file file:///Users/xxxxx/Library/Developer/CoreSimulator/Devices/346A7980-8EFB-4ACE-88FC-617C9533E893/data/Containers/Data/Application/22F22B8E-2C15-4C17-B6CD-3777B66D2AAE/Documents/ : unzipFail
Can anyone tell me what I am doing wrong?
import UIKit
import WebKit
import Zip
class ViewController: UIViewController, WKUIDelegate {
var webView: WKWebView!
override func loadView() {
let webConfiguration = WKWebViewConfiguration()
webView = WKWebView(frame: .zero, configuration: webConfiguration)
webView.uiDelegate = self
view = webView
}
override func viewWillAppear(_ animated: Bool) {
super.viewWillAppear(animated)
// Create destination URL
let documentsUrl:URL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!
let destinationFileUrl = documentsUrl.appendingPathComponent("data.tar.gz")
//Create URL to the source file you want to download
let fileURL = URL(string: "https:/www.myurl.com/data.tar.gz")
let sessionConfig = URLSessionConfiguration.default
let session = URLSession(configuration: sessionConfig)
let request = URLRequest(url:fileURL!)
let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
if let tempLocalUrl = tempLocalUrl, error == nil {
// Success
if let statusCode = (response as? HTTPURLResponse)?.statusCode {
print("Successfully downloaded. Status code: \(statusCode)")
do {
try? FileManager.default.removeItem(at: destinationFileUrl)
try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
let unzipDirectory = try Zip.quickUnzipFile(destinationFileUrl)
} catch (let writeError) {
print("Error creating a file \(documentsUrl) : \(writeError)")
}
}
} else {
print("Error took place while downloading a file. Error description: %#", error?.localizedDescription);
}
}
task.resume()
}
The problem was that the tar.gz is not supported. I used an alternative library
I have 2 functions saveImage and loadImage:
//saveImage
func saveImage(imageName: String, image: UIImage) {
guard let documentsDirectory = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first else { return }
let fileName = imageName
let fileURL = documentsDirectory.appendingPathComponent(fileName)
guard let data = image.jpegData(compressionQuality: 1) else { return }
if FileManager.default.fileExists(atPath: fileURL.path) {
do {
try FileManager.default.removeItem(atPath: fileURL.path)
print("Removed old image")
} catch let removeError {
print("couldn't remove file at path", removeError)
}
}
do {
try data.write(to: fileURL)
} catch let error {
print("error saving file with error", error)
}
}
//loadImage
func loadImageFromDocuments(fileName: String) -> UIImage? {
let documentDirectory = FileManager.SearchPathDirectory.documentDirectory
let userDomainMask = FileManager.SearchPathDomainMask.userDomainMask
let paths = NSSearchPathForDirectoriesInDomains(documentDirectory, userDomainMask, true)
if let dirPath = paths.first {
let imageUrl = URL(fileURLWithPath: dirPath).appendingPathComponent(fileName)
let image = UIImage(contentsOfFile: imageUrl.path)
return image
}
return nil
}
}
When I call in tableviewcelll like this:
self.cachedImageView.saveImage(imageName:,image:)
self.cachedImageView.loadImageFromDocuments(fileName:)
I don't how know use that.
Create image loader class like below :-
class PKImageLoader {
let imageCache = NSCache<NSString, UIImage>()
class var sharedLoader: PKImageLoader {
struct Static {
static let instance: PKImageLoader = PKImageLoader()
}
return Static.instance
}
func imageForUrl(urlPath: String, completionHandler: #escaping (_ image: UIImage?, _ url: String) -> ()) {
guard let url = urlPath.toUrl else {
return
}
if let image = imageCache.object(forKey: urlPath as NSString) {
completionHandler(image, urlPath)
}
else {
URLSession.shared.dataTask(with: url) { data, _, _ in
guard let finalData = data else { return }
DispatchQueue.main.async {
if let img = UIImage(data: finalData) {
self.imageCache.setObject(img, forKey: urlPath as NSString)
completionHandler(img, urlPath)
}
}
}.resume()
}
}
}
download an image from URL and save it (by creating UIImage Array)
you can use that array as you want.
use below extension for setting image directly to image view.
extension UIImageView {
func setImage(from urlPath: String, placeHolder: UIImage? = nil) {
self.image = placeHolder
PKImageLoader.sharedLoader.imageForUrl(urlPath: urlPath) { image, _ in
self.image = image
}
}
this one also help you
extension String {
var toUrl: URL? {
if self.hasPrefix("https://") || self.hasPrefix("http://") {
return URL(string: self)
}
else {
return URL(fileURLWithPath: self)
}
}
I have a WKWebView which displayed pdf. I want to share the file to another devices such as iPad, iPhone.... using the share button. I tried to display the pdf in preview so it will have the iOS share button the code below.
import UIKit
import WebKit
class ShowPDFView: UIViewController, UIDocumentInteractionControllerDelegate {
#IBAction func SharePDFFile(_ sender: Any) {
let fileName = "testPDF"
guard let urlPath = Bundle.main.url(forResource: fileName, withExtension: "pdf") else {return}
let controller = UIDocumentInteractionController(url: urlPath)
controller.delegate = self
controller.presentPreview(animated: true)
}
func documentInteractionControllerViewControllerForPreview(controller: UIDocumentInteractionController!) -> UIViewController! {
return self
}
func documentInteractionControllerViewForPreview(controller: UIDocumentInteractionController!) -> UIView! {
return self.view
}
func documentInteractionControllerRectForPreview(controller: UIDocumentInteractionController!) -> CGRect{
return self.view.frame
}
I got runtime error.
[MC] Reading from private effective user settings.
The preview does not loaded. Does anyone know why?
This function works for me. In Swift 4
#IBAction func SharePDFFile(_ sender: Any) {
let fm = FileManager.default
var pdfURL = (fm.urls(for: .documentDirectory, in: .userDomainMask)).last! as URL
pdfURL = pdfURL.appendingPathComponent("johnMilky.pdf") as URL
//Rename document name to "myFile.pdf"
let url = URL(fileURLWithPath: NSTemporaryDirectory()).appendingPathComponent("johnMilkyFile.pdf") as NSURL
do {
let data = try Data(contentsOf: pdfURL)
try data.write(to: url as URL)
let activitycontroller = UIActivityViewController(activityItems: [url], applicationActivities: nil)
if activitycontroller.responds(to: #selector(getter: activitycontroller.completionWithItemsHandler))
{
activitycontroller.completionWithItemsHandler = {(type, isCompleted, items, error) in
if isCompleted
{
print("completed")
}
}
}
//activitycontroller.excludedActivityTypes = [UIActivity.ActivityType.airDrop]
activitycontroller.popoverPresentationController?.sourceView = self.view
self.present(activitycontroller, animated: true, completion: nil)
}
catch {
print(error)
}
}
I have wrote some code to load all html from url and parse it to remove header. So I got the rest of the html under header to show.
However, after clicking event in the body html, the screen shows full html from the URL.
Is there any solution for this? or Did I make a mistake to approach this problem?
The code I made is below
import UIKit
import Fuzi
class ViewController: UIViewController {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
let myURLString = "http://yahoo.com"
var myHTMLString = ""
guard let myURL = URL(string: myURLString) else {
print("Error: \(myURLString) doesn't seem to be a valid URL")
return
}
do {
myHTMLString = try String(contentsOf: myURL, encoding: .utf8)
} catch let error {
print("Error: \(error)")
}
do {
// if encoding is omitted, it defaults to NSUTF8StringEncoding
let doc = try! HTMLDocument(string: myHTMLString, encoding: String.Encoding.utf8)
let fullHtml:String = (doc.firstChild(xpath: "//*")?.rawXML)!
if let header = doc.firstChild(xpath: "//body/div/header") {
let headerString:String = header.rawXML
let withoutHeader = fullHtml.replacingOccurrences(of: headerString, with: "")
webView.loadHTMLString(withoutHeader as String, baseURL: nil)
}
} catch let error{
print(error)
}
}
Try this, it works with UIWebViewNavigationType.linkClicked. You can modify it to use with other UIWebViewNavigationType.
import UIKit
import Fuzi
class ViewController: UIViewController, UIWebViewDelegate {
#IBOutlet weak var webView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
webView.delegate = self
let myURLString = "http://yahoo.com"
var myHTMLString = ""
guard let myURL = URL(string: myURLString) else {
print("Error: \(myURLString) doesn't seem to be a valid URL")
return
}
do {
myHTMLString = try String(contentsOf: myURL, encoding: .utf8)
} catch let error {
print("Error: \(error)")
}
do {
// if encoding is omitted, it defaults to NSUTF8StringEncoding
let doc = try! HTMLDocument(string: myHTMLString, encoding: String.Encoding.utf8)
let fullHtml:String = (doc.firstChild(xpath: "//*")?.rawXML)!
if let header = doc.firstChild(xpath: "//body/div/header") {
let headerString:String = header.rawXML
let withoutHeader = fullHtml.replacingOccurrences(of: headerString, with: "")
webView.loadHTMLString(withoutHeader as String, baseURL: nil)
}
} catch let error{
print(error)
}
}
func webView(_ webView: UIWebView, shouldStartLoadWith request: URLRequest, navigationType: UIWebViewNavigationType) -> Bool {
if navigationType == .linkClicked
{
let myURLString = webView.request?.url.absoluteString
webView.stopLoading()
var myHTMLString = ""
let myURL = URL(string: myURLString)
do {
myHTMLString = try String(contentsOf: myURL, encoding: .utf8)
} catch let error {
print("Error: \(error)")
}
do {
// if encoding is omitted, it defaults to NSUTF8StringEncoding
let doc = try! HTMLDocument(string: myHTMLString, encoding: String.Encoding.utf8)
let fullHtml:String = (doc.firstChild(xpath: "//*")?.rawXML)!
if let header = doc.firstChild(xpath: "//body/div/header") {
let headerString:String = header.rawXML
let withoutHeader = fullHtml.replacingOccurrences(of: headerString, with: "")
webView.loadHTMLString(withoutHeader as String, baseURL: nil)
}
} catch let error{
print(error)
}
}
return true
}
I found an answer!
Thanks to #Sherman for the hint to solve this problem.
I had to replace a line of code below
if navigationType == .linkClicked
to
if navigationType == UIWebViewNavigationType.linkClicked
Then It works!
(this is my first post here, I am sorry for any mistakes i have made)
i have code that works perfectly on the iOS simulator but once i run it on a real device it shows online a white screen and this error: com.apple.WebKit.WebContent: 113: Could not find specified service
this is my code for downloading a pdf file from firebase to the device:
#IBAction func downloadButtonPressed (sender: UIButton) {
print("zzz download button pressed")
let directoryPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true) //FileManager().url(for: .documentDirectory, in: .userDomainMask, appropriateFor: nil, create: true)
if directoryPath.count > 0 {
let documentsDirectory = directoryPath[0]
let pathURL = URL(fileURLWithPath: documentsDirectory)
let fileURL = pathURL.appendingPathComponent("\(fixture.id).pdf")
let httpsReference = FIRStorage.storage().reference(forURL: fixture.onlineManual)
print("zzz urlManual: \(fixture.onlineManual)")
let downloadTask = httpsReference.write(toFile: fileURL) {(URL, error) in
if error != nil {
print("downloadError with pdf")
print(error?.localizedDescription)
} else {
print("zzz donwload successful: \(URL!)")
let appDelegate = UIApplication.shared.delegate as! AppDelegate
let context = appDelegate.persistentContainer.viewContext
let newManual = NSEntityDescription.insertNewObject(forEntityName: "OfflineManuals", into: context)
newManual.setValue(self.fixture.id, forKey: "id")
newManual.setValue("\(URL!)", forKey: "manual")
do {
try context.save()
print("zzz manual saved to device")
} catch {
print("zzz error saving manual to core data")
}
}
}
}
}
this is the code that loads the file from the device and displays it in a WKWebView
func loadRequest() {
let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
if documentsPath.count > 0 {
let documentsDirectory = documentsPath[0]
let restorePath = documentsDirectory + "/\(manualURL!).pdf"
let url = URL(fileURLWithPath: restorePath)
print("zzz url for local file: \(url)")
let req = URLRequest(url: url)
webView.load(req)
}
}
thank you for reading!
I finally found a way to do this. I still have no clou why my code in the question does not work on real devices but this one does and since i found a lot of people with similar problems desperatly looking for an answer use this:
SWIFT3 XCODE 8 IOS 10
import UIKit
import WebKit
class ViewController: UIViewController {
#IBOutlet weak var myView: UIView!
var webView: WKWebView!
let sema = DispatchSemaphore( value: 0 )
override func viewDidLoad() {
super.viewDidLoad()
webView = WKWebView()
myView.addSubview(webView)
savePDFtoDevice()
loadPDF()
}
the LayoutSubviews is not needed but i had problems without it...
override func viewDidLayoutSubviews() {
print("zzz width: \(self.myView.frame.size.width), height: \(myView.frame.size.height)")
print("zzz width screen: \(self.view.frame.width)")
let frame = CGRect(x: 30.0, y: 30.0, width: (self.myView.frame.width - 60), height: 300)
webView.frame = frame
}
func savePDFtoDevice(){
let myURL = URL(string: "http://www.claypaky.it/media/documents/HR_Mythos_Manual_05.2016_EN.pdf")
let req = URLRequest(url: myURL!)
let session = URLSession(configuration: .default)
session.dataTask(with: req) { (data, response, error) in
if error != nil {
print("zzz error got no session")
} else {
if let pdfData = data {
var url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
url = url.appendingPathComponent("file.pdf")
print("zzz url to save: \(url)")
print("zzz got data: \(pdfData.description)")
try? data?.write(to: url)
print("zzz wrote to file")
self.sema.signal()
}
}
}.resume()
sema.wait()
}
func loadPDF() {
let url = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)[0]
print("zzz url to load from: \(url)")
do {
let content = try FileManager.default.contentsOfDirectory(at: url, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)[0]
print("zzz file: \(content)")
webView.loadFileURL(content, allowingReadAccessTo: content)
print("zzz webView loaded")
} catch {
print("zzz error with getting the contents...")
}
}
}
I tried it in my app with changing URLs and filenames etc. and it does the trick.
Finally!!!!