如果FileManager显示文档存在,则更新/更改UITableView的附件

时间:2018-01-25 07:10:23

标签: ios uitableview

在我的iOS应用中,UITableView显示音轨列表。每个文件旁边都有一个accessory button,可以在收听文件之前单击该文件以下载文件。

我的下载功能包括if / else,打印文件已被下载(如果用户已经下载)。我希望它在下载按钮的位置显示.checkmark附件,如果文件已下载,则视图打开 - 现在,只有在点击附件后才会这样做。

要设置第一个配件,我使用:

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = TableData[indexPath.row]

    cell.accessoryType = .detailDisclosureButton

    return cell
}

然后在accessoryButtonTappedForRowWith中,检查文件是否已下载并更新为复选标记,如果有:

override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
    // doSomethingWithItem(indexPath.row)

    if let audioUrl = URL(string: "https://rss.example.com.mp3") {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
        print(destinationUrl)

        // to check if it exists before downloading it
        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            print("The file already exists at path")

            let cell = tableView.cellForRow(at: indexPath)
            cell?.accessoryType = .checkmark

            // if the file doesn't exist
        } else {

            // you can use NSURLSession.sharedSession to download the data asynchronously
            URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
                guard let location = location, error == nil else { return }
                do {
                    // after downloading your file you need to move it to your destination url
                    try FileManager.default.moveItem(at: location, to: destinationUrl)
                    print("File moved to documents folder")
                } catch let error as NSError {
                    print(error.localizedDescription)
                }

            }).resume()

        }
    }

我的理论是,由于.checkmark行,需要在附件上轻敲功能发生,它不能被点击的元素一改之前,像我想要的。

有没有更好的方法来减少用户的点击?

2 个答案:

答案 0 :(得分:1)

您需要在cellForRowAt中放置if else条件,并且需要检查文件是否已经下载。在此基础上,您需要设置.checkmark.detailDisclosureButton

一种方法是在TableData中设置布尔值以检查文件是否已下载。如果您遵循这种方法,则无需在accessoryButtonTappedForRowWith中获取所选单元格,您只需要在TableData的特定索引上更改布尔标志的值,并需要重新加载单行。

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "cell", for: indexPath)

    cell.textLabel?.text = TableData[indexPath.row]

    if (TableData[indexPath.row]).isDownloaded {
        cell.accessoryType = .checkmark   
    }else {
        cell.accessoryType = .detailDisclosureButton
    }


    return cell
}

重新加载单行:

override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
    // doSomethingWithItem(indexPath.row)

    if let audioUrl = URL(string: "https://rss.example.com.mp3") {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
        print(destinationUrl)

        // to check if it exists before downloading it
        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            print("The file already exists at path")

            (TableData[indexPath]).isDownloaded = true
            tableView.reloadRows(at: [indexPath], with: UITableViewRowAnimation.none)

            // if the file doesn't exist
        } else {

            // you can use NSURLSession.sharedSession to download the data asynchronously
            URLSession.shared.downloadTask(with: audioUrl, completionHandler: { (location, response, error) -> Void in
                guard let location = location, error == nil else { return }
                do {
                    // after downloading your file you need to move it to your destination url
                    try FileManager.default.moveItem(at: location, to: destinationUrl)
                    print("File moved to documents folder")
                } catch let error as NSError {
                    print(error.localizedDescription)
                }

            }).resume()

        }
    }

答案 1 :(得分:1)

一种方法是将代码从accessoryButtonTappedForRowWith重构为另一种方法,让我们说checkIfDownloaded(at:)并从accessoryButtonTappedForRowWithcellForRowAt调用该方法:

// MARK: Utility methods
func audioURL(for indexPath: IndexPath) -> URL? {
    if let audioUrl = URL(string: "https://rss.example.com.mp3") {
        return audioUrl
    } else {
        return nil
    }
}

func fileLocation(for indexPath: IndexPath) -> URL? {
    if let audioUrl = audioURL(for: indexPath) {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
        return destinationUrl
    } else {
        return nil
    }
}

func checkIfDownloaded(at indexPath: IndexPath) -> Bool {
    // doSomethingWithItem(indexPath.row)

    if let audioUrl = URL(string: "https://rss.example.com.mp3") {

        // then lets create your document folder url
        let documentsDirectoryURL =  FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!

        // lets create your destination file url
        let destinationUrl = documentsDirectoryURL.appendingPathComponent(audioUrl.lastPathComponent)
        print(destinationUrl)

        // to check if it exists before downloading it
        if FileManager.default.fileExists(atPath: destinationUrl.path) {
            print("The file already exists at path")

            return false
        } else {
            return true
        }
    }
}

func downloadAudioIfNotDownloaded(for indexPath: IndexPath, completion: (( /* downloaded */ Bool) -> Void)?) -> URL? {
    if !checkIfDownloaded(at: indexPath),
        let audioURL = audioURL(for: indexPath),
        let destinationUrl = fileLocation(for: indexPath) {
        // you can use NSURLSession.sharedSession to download the data asynchronously
        URLSession.shared.downloadTask(with: audioURL, completionHandler: { (location, response, error) -> Void in
            guard let location = location, error == nil else {
                completion?(false)
                return }
            do {
                // after downloading your file you need to move it to your destination url
                try FileManager.default.moveItem(at: location, to: destinationUrl)
                print("File moved to documents folder")
                // success
                completion?(true)
            } catch let error as NSError {
                print(error.localizedDescription)
                completion?(false)
            }

        }).resume()
    } else {
        // was already downloaded
        completion?(true)
    }
}

// MARK: TableView delegate/datasource methods
override func tableView(_ tableView: UITableView, accessoryButtonTappedForRowWith indexPath: IndexPath) {
    downloadAudioIfNotDownloaded(for: indexPath, completion: { success in
        // fix up a new accessory view/
    })
}


override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = ...

    if checkIfDownloaded(at: indexPath) {
        cell.accessoryType = .checkmark
    } else {
        cell.accessoryType = .detailDisclosureButton
        // although if you are starting to download automaticlly here
        // make sure the user won't start it by herself while one download already is happening
        downloadAudioIfNotDownloaded(for: indexPath, completion: { success in
            // fix up a new accessory view/
        })
    }
    return cell
}