Swift: Unable to load local images in WKWebView - swift

I am attempting to load local images from my local Bundle into my WkWebView but have not been successful.
This is my index.html:
<div>
<img src='./images/test.png'>
<p>Test Para</p>
</div>
My folder structure:
- web
-- images
-- test.png
-- index.html
- ViewController
Code in ViewController that loads the HTML
Attempt 1:
let htmlPath = Bundle.main.path(forResource: "index", ofType: "html")
let htmlUrl = URL(fileURLWithPath: htmlPath!, isDirectory: true)
webView.loadFileURL(htmlUrl, allowingReadAccessTo: htmlUrl)
Attempt 2:
let url = Bundle.main.url(forResource: "index", withExtension: "html")!
webView.loadFileURL(url, allowingReadAccessTo: url)
Attempt 3:
let htmlPath = Bundle.main.path(forResource: "index", ofType: "HTML")
let folderPath = Bundle.main.bundlePath
let baseUrl = URL(fileURLWithPath: folderPath, isDirectory: true)
do {
let htmlString = try NSString(contentsOfFile: htmlPath!, encoding: String.Encoding.utf8.rawValue)
webView.loadHTMLString(htmlString as String, baseURL: baseUrl)
} catch {
// catch error
}
The solutions attempted above were suggested from this post and this. All the above returns the following result:

The problem is that this statement is wrong:
My folder structure:
- web
-- images
-- test.png
-- index.html
That may be what the Project navigator looks like, but those yellow things in the Project navigator ("web", "images") are not folders. They are just organizational devices for the Project navigator itself (groups), to help you find your stuff. In the built app, your resources are being loaded flat into the app bundle, so that test.png and index.html are at the same level together, namely, the top level of the bundle.
If what you really wanted was in fact a "web" folder with that structure inside your app bundle, then you needed this to be a folder reference, which is a very different thing.

Related

How to include a file in Test Bundle swift?

I have json file that I want to include in the test bundle so I can just read this json for my tests.
So I created a file called "test.json", it is in my Tests folder.
Now I want to read this file. I am reading it like this, the code here is in the test file in test bundle:
let bundle = Bundle(for: type(of: self))
var url = bundle.url(forResource: "test", withExtension: "json")
the url is nil every single time. I swear that file is there, if I open it in finder, it's under the same directory as the test-info.plist. I even tried the main bundle but it is still nil!!
Where is this file????
Try this:
let bundle = Bundle(for: YourTestClass.self)
let path = bundle.path(forResource: "test", ofType: "json")
let data = try Data(contentsOf: URL(fileURLWithPath: path))

How to read data from a file in the App's bundle I macOS?

I'm trying to read the data from a txt file on macOS. I use String(contentsOf:) and Bundle.main.path(forResource:) like I would on iOS. However, this doesn't work on macOS. I have tried several solutions from other posts but because of macOS they don't seem to work.
Thanks in advance.
Edit:
My code:
let path = Bundle.main.path(forResource: "file", ofType: "txt")! // no error
let url = URL(string: path)! // no error
let contents: String
do {
contents = try String(contentsOf: url)
} catch {
print(error) // Error Domain=NSCocoaErrorDomain Code=262 "The file couldn’t be opened because the specified URL type isn’t supported."
contents = "ERROR"
}
print(contents)
I can save the data to a folder on disk, but I want to ship this file with my app.
URL(string is the wrong API. It's only for URL strings starting with a scheme (http://, file://)
For file system paths you have to use URL(fileURLWithPath.
But in this situation there is a much better way
Replace
let path = Bundle.main.path(forResource: "file", ofType: "txt")!
let url = URL(string: path)! // no error
with
let url = Bundle.main.url(forResource: "file", withExtension: "txt")

Loading a Local HTML file in UIWebView

I am having trouble loading a local HTML file. Here is my code. please help.
let URL = NSBundle.mainBundle().pathForResource("index2", ofType: "html")
let request = NSURLRequest(URL: url!)
Webview.loadRequest(request)
by use the following code. I have manage to load the html file but it doesn't load up the CSS!
let htmlFile = NSBundle.mainBundle().pathForResource("index1", ofType: "html")
let html = try? String(contentsOfFile: htmlFile!, encoding: NSUTF8StringEncoding)
GSFWebView.loadHTMLString(html!, baseURL: nil)
Simply write this code inside your ViewDidLoad i have added url of this page as example, just replace it with yours. On storyboard you don't need to do anything, if you have any extra view added on you view controller as container for website then replace self.view in my code with your view.
let myWebView:UIWebView = UIWebView(frame: CGRect(x: 0, y: 0, width: UIScreen.main.bounds.width, height: UIScreen.main.bounds.height))
//add your url on line below
myWebView.loadRequest(URLRequest(url: URL(string: "https://stackoverflow.com/questions/26647447/load-local-html-into-uiwebview-using-swift")!))
self.view.addSubview(myWebView)
And if you want to load page from local file, you can do it by defining url this way.
Swift 2
let url = NSBundle.mainBundle().URLForResource("webFileName", withExtension:"html")
Swift 3
let url = Bundle.main.url(forResource: "webFileName", withExtension: "html")
I only had to add this code to the viewDidLoad method:
1- First of all, you have to get the local URL from the Bundle. (previously, I added the index.html file to the project, copying when asked)
2- Then you have to create the request URL to be loaded from the webView.
3- After all, add the new webView created as a subView from the main view.
That worked for me.
if let url = Bundle.main.url(forResource: "index", withExtension: "html"){// 1st step
webView.loadFileURL(url, allowingReadAccessTo: url)
let request = URLRequest(url: url as URL) // 2nd step
webView.load(request)
self.view.addSubview(self.webView) // 3rd step
}

Replace folder in file system using Swift

How can I copy and paste the entire content of a folder using Swift on a OS X? If the destinationPath already contains the folder, than it should replace it.
I tried
let appSupportSourceURL = NSURL(string: appSupportSourcePath)
let appSupportDestinationURL = NSURL(string: appSupportDestinationPath+"/"+appSupportFileName)
if (fileManager.isReadableFileAtPath(appSupportSourcePath)){
do {
try fileManager.copyItemAtURL(appSupportSourceURL!, toURL: appSupportDestinationURL!)}
catch{
}
}
but I realised, that this only works for files. I am trying to replace a whole folder.
I know Apple encourages new code to use the URLs to specify file system path. However NSFileManager is an old class and it's still in transition between the old string-based path and the new URL-based paradigm. Try this:
let appSupportSourcePath = "..."
let appSupportDestinationPath = "..."
let fileManager = NSFileManager.defaultManager()
do {
// Delete if already exists
if fileManager.fileExistsAtPath(appSupportDestinationPath) {
try fileManager.removeItemAtPath(appSupportDestinationPath)
}
try fileManager.copyItemAtPath(appSupportSourcePath, toPath: appSupportDestinationPath)
} catch {
print(error)
}
Edit: method with NSURL
let appSupportSourceURL = NSURL(fileURLWithPath: "...", isDirectory: true)
let appSupportDestionURL = NSURL(fileURLWithPath: "...", isDirectory: true)
try! NSFileManager.defaultManager().copyItemAtURL(appSupportSourceURL, toURL: appSupportDestionURL)

Get file path from NSBundle in Swift

I have a file stored in:
/var/mobile/Containers/Data/Application/083EA15E7/Documents/myFile.zip
It got there after I downloaded it from a server.
If I know the file name is myFile.zip, how can I find it with NSBundle?
Like this:
if let URL = NSBundle.mainBundle().URLForResource("myFile", withExtension: "zip") {
// do stuff
}
currently this returns false, not sure how I can specify the whole path. Any ideas?
This item is not in your bundle, an item in your bundle is something that you add before compiling, such as assets, fonts etc.
iOS provides each app with a sandbox. In that sandbox, the Documents folder exists. To access files from the Documents folder try this:
let documentsURL = NSURL(
fileURLWithPath: NSSearchPathForDirectoriesInDomains(
.DocumentDirectory, .UserDomainMask, true).first!,
isDirectory: true
)
To get the file, you will need to get its path and append it to the documents path like so.
let URLToMyFile = documentsURL.URLByAppendingPathComponent("MyFile.zip")
To get the path as a string you can access the path property of the URL.
print(URLToMyPath.path!)
That will print out the path of your downloaded resource.
Tested on: xCode 8.3.2 & Swift 3.1
First drag your file (JPG, MP3, ZIP) inside your project folder and make sure Copy items if needed is checked and project/app is selected in Add to targets
Inside relevant ViewController
let fileName = "fileName"
let fileType = "fileType"
if let filePath = Bundle.main.path(forResource: fileName, ofType: fileType) {
print(filePath)
}
If you need to get the file URL you can use NSBundle method
if let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileType) {
print(fileURL)
}
Also NSBundle method pathForResource has an initializer that you can specify in which directory your files are located like:
if let filePath = Bundle.main.path(forResource: fileName, ofType: fileType, inDirectory: "filesSubDirectory") {
print(filePath)
}
And for getting file URL:
if let fileURL = Bundle.main.url(forResource: fileName, withExtension: fileType, subdirectory: "filesSubDirectory") {
print(fileURL)
}
run time created file are stored in Document directory not in NSBundle. NSBundle stores the files like System file you put in your Xcode project while your developing
Here is the example
This code is fully tested on Swift 2.0
let file = "myFile.zip"
if let dir : NSString = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.AllDomainsMask, true).first {
//path will be stored here
let sPath = dir.stringByAppendingPathComponent(file);
print(sPath) // printing the file path
}