Reputation: 3
Below code is work. The images are saved successfully in document directory, but the problem is only first time the collectionViewController can load images with path successfully. I have to delete all images to store new images or it will show the error message
"fatal error: unexpectedly found nil while unwrapping an Optional value".
Because the path is unavailable, readnsdata = NSData(contentsOfFile: filepath)!
will cause error.
I have no idea why only the first time it can work.
path : "/var/mobile/Containers/Data/Application/29306029-BDCF-4BEA-93A6-D5626CBAAA90/Documents/x.jpg"
func writeNSDataToDisk(imageData:NSData){
let myindex = imgPathArray.count
let fileName = "\(self.imgPathArray.count)"
let paths = NSSearchPathForDirectoriesInDomains(NSSearchPathDirectory.DocumentDirectory, NSSearchPathDomainMask.UserDomainMask, true)
let docs: String = paths[0] as String
let filepath: String = (docs as NSString).stringByAppendingPathComponent("\(fileName).jpg")
let test = imageData.writeToFile(filepath, atomically: true)
if test {
self.imgPathArray.insert(filepath, atIndex: myindex)
print("The picture \(fileName).jpg is been saved.")
self.readORwriteList(true)//write list to txt file
}
print(self.imgPathArray)
}
func readNSDataFromDisk(fileIndex:Int) -> NSData{
let checkValidation = NSFileManager.defaultManager()
var readnsdata = NSData()
if (fileIndex <= self.imgPathArray.count) {
let filepath = self.imgPathArray[fileIndex]
if (checkValidation.fileExistsAtPath(filepath)){
print("File is available")
print("load \(fileIndex).jpg,filepath is \(filepath)")
readnsdata = NSData(contentsOfFile: filepath)!
if readnsdata.length != 0 {
getImageProperties(readnsdata)
}
}
else{
print("File is not available!!!")
}
}
return readnsdata
}
The solution to my problem :
Instead of storing absolute file path, I name the files in a regular way and search them by their name. There is no need to store path.
The URLs for the files are now constructed relative to the Documents directory URL every time the app is run.
Thanks
Upvotes: 0
Views: 1338
Reputation: 5136
First a side note. Apple's docs specifically recommend against using fileExistsAtPath
the way you're doing it here.
NOTE
Attempting to predicate behavior based on the current state of the file system or a particular file on the file system is not recommended. Doing so can cause odd behavior or race conditions. It’s far better to attempt an operation (such as loading a file or creating a directory), check for errors, and handle those errors gracefully than it is to try to figure out ahead of time whether the operation will succeed.
Try replacing this…
if (checkValidation.fileExistsAtPath(filepath)){
print("File is available")
print("load \(fileIndex).jpg,filepath is \(filepath)")
readnsdata = NSData(contentsOfFile: filepath)!
if readnsdata.length != 0 {
getImageProperties(readnsdata)
}
}
else{
print("File is not available!!!")
}
…with this…
do {
readnsdata = try NSData(contentsOfFile: filepath, options: .DataReadingMappedIfSafe)
if readnsdata.length != 0 {
getImageProperties(readnsdata)
}
}
catch let e {
print("Couldn't read file at \(filepath) because \(e)")
}
This approach gives you the information you were looking for without having to speculate. Just run your code and see what happens when the NSData initializer throws! :)
[Update: Off-topic opinion]
While it's a good habit not to sprinkle a long method with returns, there's not a lot going on here. Personally, I think the code comes out more readable without the temporary readnsdata
variable. This way, imo, both the happy path and the default return values are clear on first reading:
func readNSDataFromDisk2(fileIndex:Int) -> NSData{
if (fileIndex <= self.imgPathArray.count) {
let path = self.imgPathArray[fileIndex]
do {
let data = try NSData(contentsOfFile: path, options: .DataReadingMappedIfSafe)
if data.length != 0 {
getImageProperties(data)
}
return data
}
catch let e {
print("Couldn't read file at \(path) because \(e)")
}
}
return NSData()
}
Upvotes: 3
Reputation: 27448
replace readnsdata = NSData(contentsOfFile: filepath)!
with readnsdata = NSData(contentsOfFile: filepath)?
. hope this will help :)
Upvotes: 0