Search code examples
iosswiftuitableviewpdfkitnsdocumentdirectory

PDFKIT , Swift How to remove pdf (PDFDocument) from uitableview


i have this code for download PDF file :

var documents = [PDFDocument]()

  DispatchQueue.global(qos: .default).async(execute: {
            //All stuff here

            print("Download PDF");
            let url=NSURL(string: urlString);
            let urlData=NSData(contentsOf: url! as URL);

            if((urlData) != nil)
            {
                let documentsPath = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)[0]

                let fileName = urlString as NSString;

                let filePath="\(documentsPath)/\(fileName.lastPathComponent)";

                let fileExists = FileManager().fileExists(atPath: filePath)

                if(fileExists){

                    // File is already downloaded
                    print("PDF Already Downloaded");
                }
                else{

                    //download
                    DispatchQueue.main.async(execute: { () -> Void in

                        print(filePath)
                        urlData?.write(toFile: filePath, atomically: true);
                        print("PDF Saved");

                        self.refreshData()
                    })
                }
            }
        })

Now I want to remove this file from uitableview in table and in documentdirecotry how to use index path row and how to find file name for removing

i know i will remove the file here but i don't know how to exactly remove the PDF in documentDirectory and Table

override func tableView(_ tableView: UITableView, canEditRowAt indexPath: IndexPath) -> Bool {
    return true
}

override func tableView(_ tableView: UITableView, commit editingStyle: UITableViewCellEditingStyle, forRowAt indexPath: IndexPath) {
    if (editingStyle == UITableViewCellEditingStyle.delete) {
        // handle delete (by removing the data from your array and updating the tableview)

    }

}

here is my table view cell

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

        let document = documents[indexPath.row]
        if let documentAttributes = document.documentAttributes {
            if let title = documentAttributes["Title"] as? String {
                cell.title = title
            }
            if let author = documentAttributes["Author"] as? String {
                cell.author = author
            }

here is my refresh data part

let fileManager = FileManager.default
    let documentDirectory = fileManager.urls(for: .documentDirectory, in: .userDomainMask)[0]
    let contents = try! fileManager.contentsOfDirectory(at: documentDirectory, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
    documents = contents.flatMap { PDFDocument(url: $0) }

Solution

  • You will need to complete three steps to properly delete the document and update your table view:

    1. Use FileManager's removeItem(at: URL) or removeItem(atPath: String) to delete the file from disk. (note that both of these methods throw so you need to use a do-catch block along with try and only proceed if the method didn't throw an error.) Update: If you look at the documentation for PDFDocument you will find that in addition to the documentAttributes that you are already using there is another optional property, documentURL that should give you exactly what you need to remove it.

    2. Remove the document from documents (you could just refresh the whole array using your existing code but removing a single item is faster). documents.remove(at: indexPath.row)

    3. Finally, you need to tell the table view to remove the row in question (you could of course just reload the whole table view but removing the single cell is cleaner) tableView.deleteRows(at: [indexPath], with .fade)

    In case you are unfamiliar with do-catch blocks here is a bit of code from Apple's book on Swift (see below for link) simplified a bit:

    do {
        try makeASandwich()
        eatASandwich() // This only gets called if the line above worked
    } catch {
        dealWithTheError() // This only gets called if makeASandwich() throws an error
    }
    

    Side Note

    Apple has a fantastic guide on the Swift Language if you haven't done so yet I suggest reading, at least, The Basics. This will give you a base understanding of the language. If you are also new to programming I would suggest going through Apple's Learn to Code series that is free on iPads in the Swift Playgrounds app. The series will guide you through all the basics of programming giving you the tools to search through the documentation that Apple provides and find answers to your questions.

    We all started at the beginning at some point, and we all had to crawl before we could walk and well before we could run.