Swift - 文件路径不可用,除非是第一次使用

Swift - The file path is unavailable except for first time use

下面的代码是有效的。图像已成功保存在文档目录中,但问题只是第一次 collectionViewController 可以成功加载带有路径的图像。我必须删除所有图像才能存储新图像,否则会显示错误消息

"fatal error: unexpectedly found nil while unwrapping an Optional value".

因为路径不可用,readnsdata = NSData(contentsOfFile: filepath)!会报错

我不知道为什么只有第一次可以。

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
}

我的问题的解决方案:

我没有存储绝对文件路径,而是以常规方式命名文件并按名称搜索它们。不需要存储路径。

文件的 URL 现在是相对于文档目录 URL 每次应用 运行 构建的。

谢谢

readnsdata = NSData(contentsOfFile: filepath)! 替换为 readnsdata = NSData(contentsOfFile: filepath)?。希望这会有所帮助:)

首先是旁注。 Apple 的 docs 特别建议不要像您在这里那样使用 fileExistsAtPath

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.

尝试替换这个…

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!!!")
}

...有了这个...

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)")
}

这种方法无需推测即可为您提供所需的信息。只是 运行 你的代码,看看当 NSData 初始化程序抛出时会发生什么! :)


[更新:题外话]

虽然不要在长方法中使用 return 是个好习惯,但这里并没有太多内容。就个人而言,我认为代码在没有临时 readnsdata 变量的情况下更具可读性。这样,imo,快乐路径和默认 return 值在第一次阅读时都很清楚:

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()
}