Cannot write to Documents folder on iOS10.3 using Swift3 [duplicate] - ios

How is it possible?
let exists = NSFileManager.defaultManager().fileExistsAtPath(path.absoluteString)
print("exists: \(exists)") //false
This is path.absoluteString
//file:///Users/kuna/Library/Developer/CoreSimulator/Devices/92BD140D-5C14-43C4-80D6-904BB9594ED6/data/Containers/Data/Application/5B818832-BB19-4047-A7F8-1487F36868D6/Documents/wishlists/68/147/128/IMG_0006.PNG
And you can see it is there where it should be:
What is going on?

(The code in this answer has been updated for Swift 3 and later.)
Apparently your path variable is a NSURL (describing a file path). To get the path as
a string, use the path property, not absoluteString:
let exists = FileManager.default.fileExists(atPath: path.path)
absoluteString returns the URL in a string format, including
the file: scheme etc.
Example:
let url = URL(fileURLWithPath: "/path/to/foo.txt")
// This is what you did:
print(url.absoluteString)
// Output: file:///path/to/foo.txt
// This is what you want:
print(url.path)
// Output: /path/to/foo.txt

If you want to check if a path exist,you should check path
let url = NSURL(string: "balabala")
let path = url?.path
//Check path

Related

value of type String has no member stringByAppendingPathComponet [duplicate]

I have a project which I am migrating from Obj-C to Swift 3.0 (and I am quite a noob in Swift).
How do I translate this line?
NSString *folder = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myfolder"];
I managed to get resource path:
let resoursePath = Bundle.main.resoursePath;
But how do I get path to a subfolder named "myfolder"?
I need to get a path the subfolder, not path to the files inside it.
In Swift-3 make URL, and call appendingPathComponent:
let resourcePath = Bundle.main.resourcePath
let subdir = URL(fileURLWithPath:resourcePath!).appendingPathComponent("sub").path
or simply
let subdir = Bundle.main.resourceURL!.appendingPathComponent("sub").path
(thanks, Martin R!)
See this Q&A on information on stringByAppendingPathComponent method in Swift.
You can do something like this:
let folderURL = resourceURL(to: "myfolder")
func resourceURL(to path: String) -> URL? {
return URL(string: path, relativeTo: Bundle.main.resourceURL)
}
You can use this method to get listing of the bundle subdirectory and get resources only of the specific type:
Bundle.main.paths(forResourcesOfType: type, inDirectory: folder)
Swift 5.0
Swift 5:
Caveat: Assumes that your folder is actually in the bundle; (that you added the folder to the project via 'Add Folder Reference', not by the 'Add Groups' option).
bundle.main.path(forResource: "myfolder", ofType: nil)
Objective-C: (your example)
NSString *folder = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myfolder"];
Other Swift ways:
As a URL (Apple's preferred method, the :URL? is only included here to clarify that this does not produce a string):
let folderURL:URL? = Bundle.main.url(forResource: "myfolder", withExtension: nil)
Appending as a string:
let folder = Bundle.main.resourcePath?.appending("/myfolder")
// or
let y = Bundle.main.resourcePath?.appending("/").appending("myfolder")
The following literal translation fails, as appendingPathComponent is no longer available in the Swift String type which is slightly different from NSString:
let folder = Bundle.main.resourcePath?.appendingPathComponent("myfolder")

How to get path to a subfolder in main bundle?

I have a project which I am migrating from Obj-C to Swift 3.0 (and I am quite a noob in Swift).
How do I translate this line?
NSString *folder = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myfolder"];
I managed to get resource path:
let resoursePath = Bundle.main.resoursePath;
But how do I get path to a subfolder named "myfolder"?
I need to get a path the subfolder, not path to the files inside it.
In Swift-3 make URL, and call appendingPathComponent:
let resourcePath = Bundle.main.resourcePath
let subdir = URL(fileURLWithPath:resourcePath!).appendingPathComponent("sub").path
or simply
let subdir = Bundle.main.resourceURL!.appendingPathComponent("sub").path
(thanks, Martin R!)
See this Q&A on information on stringByAppendingPathComponent method in Swift.
You can do something like this:
let folderURL = resourceURL(to: "myfolder")
func resourceURL(to path: String) -> URL? {
return URL(string: path, relativeTo: Bundle.main.resourceURL)
}
You can use this method to get listing of the bundle subdirectory and get resources only of the specific type:
Bundle.main.paths(forResourcesOfType: type, inDirectory: folder)
Swift 5.0
Swift 5:
Caveat: Assumes that your folder is actually in the bundle; (that you added the folder to the project via 'Add Folder Reference', not by the 'Add Groups' option).
bundle.main.path(forResource: "myfolder", ofType: nil)
Objective-C: (your example)
NSString *folder = [[[NSBundle mainBundle] resourcePath] stringByAppendingPathComponent:#"myfolder"];
Other Swift ways:
As a URL (Apple's preferred method, the :URL? is only included here to clarify that this does not produce a string):
let folderURL:URL? = Bundle.main.url(forResource: "myfolder", withExtension: nil)
Appending as a string:
let folder = Bundle.main.resourcePath?.appending("/myfolder")
// or
let y = Bundle.main.resourcePath?.appending("/").appending("myfolder")
The following literal translation fails, as appendingPathComponent is no longer available in the Swift String type which is slightly different from NSString:
let folder = Bundle.main.resourcePath?.appendingPathComponent("myfolder")

Conversion From String to NSURL constantly returns nil

I am trying to fetch the path of an audio file that I have added to the main bundle of my app. When I print the path as String it prints normally.
But, when I try to print the NSURL of the same after converting it, returns a nil
let audioPath: String = NSBundle.mainBundle().pathForResource("Test", ofType: "mp3")!
print(audioPath)
let audioPathURL: NSURL? = NSURL(string: audioPath)
print(audioPathURL)
You need to use the filePath specific initialiser
let audioPathURL: NSURL? = NSURL(fileURLWithPath: audioPath)
An URL in the file system must be initialized with the method NSURL(fileURLWithPath:) not NSURL(string:).
Or you use the URL based methods of NSBundle

NSBundle.mainBundle().pathForResource returns nil

I am trying to write a simple IO wrapper for Swift.
To test this I have a file named "Test.txt" in my project root.
I have added this file to Build Phases within Build Bundle Resources, as suggested by everyone else who has had this problem.
I have implemented a very simple File class with one read function with the intent to output the contents of the file.
class File2{
let resourceName: String
let type: String
let bundle = NSBundle.mainBundle()
init(resourceName: String, type: String = "txt"){
self.resourceName = resourceName
self.type = type
println(self.bundle)
}
func read(){
let path = self.bundle.pathForResource("Test.txt", ofType: "txt") //Hard coded these in just to make sure Strings contained no whitespace
println(path) //This returns nil...why?
var error:NSError?
//print(String(contentsOfFile:path!, encoding:NSUTF8StringEncoding, error: &error)!)
//return String(contentsOfFile:path!, encoding:NSUTF8StringEncoding, error: &error)!
}
}
When I print the contents of the bundle I get a URI to a specific location on my filesystem, which I assume is the virtual location of the app in the simulator. Navigating to it reveals that it does indeed contain my "Test.txt" file.
Now all I want to do is get the path to that file.
I do this by calling: self.bundle.pathForResource("Test.txt", ofType: "txt")
This returns "nil"
Why? :)
Do not include the .txt in the name parameter, pass it as the extension parameter.
From the documentation:
extension
The filename extension of the file to locate.
If you specify an empty string or nil, the extension is assumed not to exist and the file is the first file encountered that exactly matches name.
Swift3
let bundle = Bundle.main
let path = bundle.path(forResource: "Test", ofType: "txt")
Swift1 & Swift2
let bundle = NSBundle.mainBundle()
let path = self.bundle.pathForResource("Test", ofType: "txt")
Objective-C
NSBundle* bundle = [NSBundle mainBundle];
NSString* path = [bundle pathForResource:#"Test" ofType:#"txt"];
In swift 3.0, write with
let path = Bundle.main.path(forResource: "Test", ofType: "txt")
Replace your
let path = self.bundle.pathForResource("Test.txt", ofType: "txt")
with
let path = NSBundle.mainBundle().pathForResource("Test", ofType: "txt")
Replace
let path = self.bundle.pathForResource("Test.txt", ofType: "txt")
with
let path = self.bundle.pathForResource("Test", ofType: "txt")
Another reason for NSBundle.mainBundle().pathForResource returns nil is file is not properly added to the target. When you drag and drop the file in bundle, please make sure that "Add To Target" checkbox and "Copy items if needed" checkbox is selected.
For those of you who are trying to access resources in Unit Tests, I faced a problem where the resource was not found in the main bundle and my solution was to search for the path in all bundles, this way I don't have to specify a bundle identifier, where fileName is a string passed into the function and of course the type can be anything you'd want.
NSString *path;
for (NSBundle *bundle in [NSBundle allBundles]) {
path = [bundle pathForResource:fileName ofType:#"json"];
if (path) {
break; // Here is your path.
}
}
The ofType parameter appended to the resource name, so replace this line:
let path = self.bundle.pathForResource("Test.txt", ofType: "txt")
to something like this:
let path = self.bundle.pathForResource("Test", ofType: "txt")
The Build Bundle Resources is also necessary to check.

`NSBundle.mainBundle().URLForResource` always returns `nil`

I am new to Swift and am using Xcode 6.
I am attempting to read data from the app's plist file, but it is not working.
The data.plist file is included in Xcode's Supporting Files group.
I am using the code below:
var dataList = NSDictionary(contentsOfURL:NSBundle.mainBundle().URLForResource("data", withExtension:"plist"))
however the NSURL:
NSBundle.mainBundle().URLForResource("data", withExtension:"plist")
always returns nil.
I don't know what is wrong.
Generally you would want to use this code to create your plist. This finds the the path to your plist and then moves it into the documents directory if it isn't already there. If you don't move it, you are not allowed to write to it, hence this chunk of code is vital. To fetch the information from the plist, use the second bit of code. Obviously if you have an array rather than a dictionary, you would have to alter it to deal with that.
var path = NSSearchPathForDirectoriesInDomains(.DocumentDirectory, .UserDomainMask, true)[0] as NSString
path = path.stringByAppendingPathComponent("data.plist")
let fileManager = NSFileManager.defaultManager()
if !fileManager.fileExistsAtPath(path) {
let sourcePath = NSBundle.mainBundle().pathForResource("data", ofType: "plist")
fileManager.copyItemAtPath(sourcePath, toPath: path, error: nil)
}
.
let dict = NSMutableDictionary(contentsOfFile: path) as NSMutableDictionary

Resources