FileManager replaceItemAt()导致EXC_BAD_ACCESS

时间:2016-10-08 08:50:24

标签: swift3 exc-bad-access ios10 nsfilemanager

我写过一个从网站下载图片的应用程序。 如果设备上已存在此图像,我正在尝试更换它。

func urlSession(_ session: URLSession, downloadTask: URLSessionDownloadTask, didFinishDownloadingTo location: URL) {
    let userId = Int.init(downloadTask.taskDescription!)! // task description is definetly set in downloadImage() and is an Int
    guard let target = imageFolder?.appendingPathComponent("\(userId).jpg") else {
        delegate?.imageDownloadFailed(forUser: userId, error: "Could not create target URL.")
        return
    }

    do {
        if fileManager.fileExists(atPath: target.path) {
            _ = try fileManager.replaceItemAt(target, withItemAt: location)
        } else {
            try fileManager.moveItem(at: location, to: target)
        }
        delegate?.savedImage(forUser: userId, at: target)
    } catch let error {
        delegate?.imageDownloadFailed(forUser: userId, error: error.localizedDescription)
    }
}

问题出现在if - 声明中:

_ = try fileManager.replaceItemAt(target, withItemAt: location)

我总是EXC_BAD_ACCESS,但我找不到错误。 fileManagertargetlocation是非零的。 我已经尝试将代码同步发送到主线程,但错误仍然存​​在。

有任何建议吗?

编辑:

由于我不是唯一一个遇到此错误的人,所以我决定在Apple创建一个错误报告。 该报告可在Open Radar获得; click

我还上传了一个playground file at pastebin.com来演示错误,并提供类似于naudec的快速解决方案。

2 个答案:

答案 0 :(得分:3)

有同样的问题。写完我自己的版本:

let fileManager = FileManager.default

func copyItem(at srcURL: URL, to dstURL: URL) {
    do {
        try fileManager.copyItem(at: srcURL, to: dstURL)
    } catch let error as NSError {
        if error.code == NSFileWriteFileExistsError {
            print("File exists. Trying to replace")
            replaceItem(at: dstURL, with: srcURL)
        }
    }
}

func replaceItem(at dstURL: URL, with srcURL: URL) {
    do {
        try fileManager.removeItem(at: dstURL)
        copyItem(at: srcURL, to: dstURL)
    } catch let error as NSError {
        print(error.localizedDescription)
    }
}

我先拨打copyItem

答案 1 :(得分:0)

在您的下载完成并释放filemanager时,持有此方法的类不再存在。在完成闭包中创建FileManager

...
let localFilemanager = FileManager.default
do {
...