How to load Microsoft file like docx in swift via UIWebView - swift

I have been working on ios app which now i am facing some problems. I want to load some files like docx, xls using UIWebView. It gets me white screen on my actual device.
#IBOutlet weak var fileServerWebView: UIWebView!
override func viewDidLoad() {
super.viewDidLoad()
if let path = Bundle.main.path(forResource: "easychair", ofType: "docx"){
let targetUrl: URL = URL(fileURLWithPath: path)
let request = URLRequest(url: targetUrl as URL)
fileServerWebView.delegate = self
fileServerWebView.scalesPageToFit = true
fileServerWebView.loadRequest(request)
}else{
print("cannot get path")
}
// Do any additional setup after loading the view.
}
That is code that i tried to load that file from local. Thank you for your help.

Related

Why is my local video file path within the document directory not working after some time? [Swift]

I have a custom video recording view controller, in which I save using a URL:
Sample URL: file:///var/mobile/Containers/Data/Application/802497BB-8413-4245-B33A-708EF8DD9CAF/Documents/FA6AF78A-2692-4CC8-8BE2-7F18140C3C98.mp4
The URL is generated using these functions:
// Gets the directory that the video is stored in
func getPathDirectory() -> URL {
// Searches a FileManager for paths and returns the first one
let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask)
let documentDirectory = paths[0]
return documentDirectory
}
func generateURL() -> URL? {
let path = getPathDirectory().appendingPathComponent(NSUUID().uuidString + ".mp4")
return path
}
I then replay the video once in a separate playback controller, and it works no problem. I have included it right below:
import AVFoundation
class VideoPlaybackController: UIViewController {
let avPlayer = AVPlayer()
var avPlayerLayer: AVPlayerLayer!
var videoURL: URL!
#IBOutlet weak var videoView: UIView!
override func viewDidLoad() {
super.viewDidLoad()
// print("VideoPlaybackController: \(videoURL!)")
avPlayerLayer = AVPlayerLayer(player: avPlayer)
avPlayerLayer.frame = view.bounds
avPlayerLayer.videoGravity = AVLayerVideoGravity.resizeAspectFill
videoView.layer.insertSublayer(avPlayerLayer, at: 0)
view.layoutIfNeeded()
let playerItem = AVPlayerItem(url: self.videoURL as URL)
avPlayer.replaceCurrentItem(with: playerItem)
avPlayer.play()
}
}
While the video works, after some time, the video cannot be replayed, even though I saved it within the document directory. I downloaded the xcappdata and looked within the contents of the app, and saw that the video file is still there, so I am confused as to why the video is not available after some time.
Is there something that I am missing? Thank you for your time.

Swift xcode macos PDFDocument(url: URL) does not create document

I am trying to learn how to display a .pdf file in Swift in an xcode project. I have code that works if the target file is in the project's bundle, but I cannot display a .pdf that is elsewhere in my user space. In the code that follows (lower half), "pdfURL2" prints out and is the correct URL. The code prints out "File Exists", so I know that the target file is accessible. It is a valid .pdf file that I can open with Preview. Using the xcode debugger, "test" is "nil". Following that, "pdfView.document = test" opens a view, but it is, of course, empty. If I surround the "test = PDFDocument(url: pdfURL2)" declaration with a guard" statement, the thread crashes. Hence, I have left that out.
How do I display a .pdf file that is not explicitly in xcode"s project bundle?
CODE FOLLOWS:
import Cocoa
import Quartz
class PDFViewController: NSViewController {
#IBOutlet weak var pdfView: PDFView!
override func viewDidLoad() {
super.viewDidLoad()
let fm = FileManager.default
// THIS Code does WORK (for test.pdf in bundle)
guard let pdfURL = Bundle.main.url(forResource: "test", withExtension: "pdf")
else { fatalError("PDF not found") }
guard let pdfDocument = PDFDocument(url: pdfURL)
else { fatalError("PDF document not created") }
pdfView.document = pdfDocument
// END of code that does WORK (for test.pdf in bundle)
// THis Code does NOT WORK for buildFile.pdf NOT in bundle
let pdfPath2 = "/Users/myaccount/Desktop/Problematic/buildFile.pdf"
let pdfURL2 = URL(fileURLWithPath: pdfPath2)
print("pdfURL2 = \(pdfURL2)")
if fm.fileExists(atPath: pdfPath2){
print("File Exists")
var test = PDFDocument(url: pdfURL2)
pdfView.document = test
}
// Do any additional setup after loading the view.
} // End ViewDidLoad
} // End PDFViewController

cannot view pdf to web view using file path

i have an app to download pdf file. If the download completed it have a path like
file:///Users/developer/Library/Developer/CoreSimulator/Devices/F9AB746D-20C3-4333-AE70-2840538F4AED/data/Containers/Data/Application/861FA32B-06AA-4176-A499-B4BB8DF224C1/Library/Caches/pdffile.pdf
I try to view using this
#IBOutlet weak var webView: UIWebView!
var path = ""
var receiveData: String = "" //this contain file:///Users/developer.../Caches/pdffile.pdf
override func viewDidLoad() {
super.viewDidLoad()
let url = NSURL.fileURLWithPath(receiveData)
print(url)
self.webView.loadRequest(NSURLRequest(URL: url))
}
the build succeded and no error butstill can't view the pdf file
what's wrong?
Change your NSURL path, you need to use receiveData, because that already contain the path of the file, NSBundle is use when you have file inside your project directory.
let url = NSURL.fileURLWithPath(receiveData)

Saving WebView to PDF returns blank image?

I'm trying to figure out how to save a WebView to a PDF and totally stuck, would really appreciate some help?
I'm doing this in Cocoa & Swift on OSX, here's my code so far:
import Cocoa
import WebKit
class ViewController: NSViewController {
override func loadView() {
super.loadView()
}
override func viewDidLoad() {
super.viewDidLoad()
loadHTMLString()
}
func loadHTMLString() {
let webView = WKWebView(frame: self.view.frame)
webView.loadHTMLString("<html><body><p>Hello, World!</p></body></html>", baseURL: nil)
self.view.addSubview(webView)
createPDFFromView(webView, saveToDocumentWithFileName: "test.pdf")
}
func createPDFFromView(view: NSView, saveToDocumentWithFileName fileName: String) {
let pdfData = view.dataWithPDFInsideRect(view.bounds)
if let documentDirectories = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true).first {
let documentsFileName = documentDirectories + "/" + fileName
debugPrint(documentsFileName)
pdfData.writeToFile(documentsFileName, atomically: false)
}
}
}
It's pretty simple, what I'm doing is creating a WebView and writing some basic html content to it which renders this:
And then takes the view and saves it to a PDF file but that comes out blank:
I've tried grabbing the contents from the webView and View but no joy.
I've found a similar problem here How to take a screenshot when a webview finished rending regarding saving the webview to an image, but so far no luck with an OSX Solution.
Could it be something to do with the document dimensions?
or that the contents is in a subview?
maybe if you capture the View you can't capture the SubView?
Any ideas?
iOS 11.0 and above, Apple has provided following API to capture snapshot of WKWebView.
#available(iOS 11.0, *)
open func takeSnapshot(with snapshotConfiguration: WKSnapshotConfiguration?, completionHandler: #escaping (UIImage?, Error?) -> Swift.Void)
Sample usage:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
if #available(iOS 11.0, *) {
webView.takeSnapshot(with: nil) { (image, error) in
//Do your stuff with image
}
}
}
iOS 10 and below, UIWebView has to be used to capture snapshot. Following method can be used to achieve that.
func webViewDidFinishLoad(_ webView: UIWebView) {
let image = captureScreen(webView: webView)
//Do your stuff with image
}
func captureScreen(webView: UIWebView) -> UIImage {
UIGraphicsBeginImageContext(webView.bounds.size)
webView.layer.render(in: UIGraphicsGetCurrentContext()!)
let image: UIImage = UIGraphicsGetImageFromCurrentImageContext()!
UIGraphicsEndImageContext()
return image
}
Here's another relevant answer
So I kind of figured out how to solve it, it turns out you can't (especially on OSX) access and print a webview from a WKWebView.
You have to use a WebView and NOT a WKWebView (I originally started with WKWebView because a few of the articles I read said to use that).
A WebView object is pretty much similar to a WKWebView object, which is fun as hell :-)
But it gives you access to .mainFrame & .frameView which you'll need to print it's content.
Here's my code:
let webView = WebView(frame: self.view.frame)
let localfilePath = NSBundle.mainBundle().URLForResource(fileName, withExtension: "html");
let req = NSURLRequest(URL: localfilePath!);
webView.mainFrame.loadRequest(req)
self.view.addSubview(webView)
Once it's rendered I then added a 1 second delay just to make sure the content has rendered before I print it,
// needs 1 second delay
let delay = 1 * Double(NSEC_PER_SEC)
let time = dispatch_time(DISPATCH_TIME_NOW, Int64(delay))
dispatch_after(time, dispatch_get_main_queue()) {
// works!
let data = webView.dataWithPDFInsideRect(webView.frame)
let doc = PDFDocument.init(data: data)
doc.writeToFile("/Users/john/Desktop/test.pdf")
// works!
let printInfo = NSPrintInfo.sharedPrintInfo()
let printOperation = NSPrintOperation(view: webView.mainFrame.frameView, printInfo: printInfo)
printOperation.runOperation()
}
Here I'm printing it and saving it as a PDF, just so I'm doubly sure it works in all circumstances.
I'm sure it can be improved, I hate the delay hack, should replace that with some kind of callback or delegate to run when the content has fully loaded.

Injecting a new stylesheet into a website via uiwebview using iOS8 Swift XCode 6

I've seen a few options on here using just Objective-C, but I'm having trouble doing this with Swift iOS8 in XCode 6. I'm using the uiwebview to load a website. For sake of example, let's say its google.com.
#IBOutlet var website: UIWebView!
var url = "http://www.google.com"
func loadUrl() {
let requestURL = NSURL(string: url)
let request = NSURLRequest(URL: requestURL!)
website.loadRequest(request)
}
override func viewDidLoad() {
super.viewDidLoad()
website.delegate = self
loadUrl()
}
func webViewDidFinishLoad(website: UIWebView) {
var jsscript = "some script here"
website.stringByEvaluatingJavaScriptFromString(jsscript)
}
Using Swift, how would I inject a whole new stylesheet into the website so I can overwrite many of the styles?
Also, I'd like the new stylesheet to exist in one of my app's directories. Where is the best directory for that to be? Under "Supporting files?" And, how would I call that path in my code?
It would also be nice if the website wouldn't load until the styles had been applied.
So, I think I found at least one way to accomplish appending styles to the webpage being loaded using Swift:
var loadStyles = "var script =
document.createElement('link');
script.type = 'text/css';
script.rel = 'stylesheet';
script.href = 'http://fake-url/styles.css';
document.getElementsByTagName('body')[0].appendChild(script);"
website.stringByEvaluatingJavaScriptFromString(loadStyles)
Using the now preferred WKWebView you can put the external css file, say tweaks.css in the root of your project or in a sub-folder, then you can inject it into your page like this:
func webView(_ webView: WKWebView, didFinish navigation: WKNavigation!) {
guard let path = Bundle.main.path(forResource: "tweaks", ofType: "css") else { return }
let css = try! String(contentsOfFile: path).replacingOccurrences(of: "\\n", with: "", options: .regularExpression)
let js = "var style = document.createElement('style'); style.innerHTML = '\(css)'; document.head.appendChild(style);"
webView.evaluateJavaScript(js)
}
To make the file available:
Click your project
Click your target
Select Build Phases
Expand Copy Bundle Resources
Click '+' and select your file.
Also make sure that your controller implements WKNavigationDelegate:
class ViewController: UIViewController, WKNavigationDelegate