如何使用 UIDocumentPicker 将 pdf 文件导入表格视图单元格

Posted

技术标签:

【中文标题】如何使用 UIDocumentPicker 将 pdf 文件导入表格视图单元格【英文标题】:How to import pdf files to table view cells using UIDocumentPicker 【发布时间】:2018-04-16 05:59:00 【问题描述】:

我真的很纠结如何导入 pdf 文件并将其存储在表格视图单元格中。我正在使用 UIDocumentPicker 导入 pdf 文件,但我无法弄清楚如何将 pdf 文件数据存储到表格视图单元格中。我的问题是我创建了一个名为 insertNewFileTitle() 的函数,每次单击 addButtonTapped 函数时都会附加一个新的表格视图单元格。我想确保 pdf 数据仍然在我导入 pdf 文件的正确表格视图单元格中。

我想要做的是让表格视图单元格存储导入的 pdf 文件,以便稍后在选择表格单元格时,我可以将 pdf 文件作为邮件编写器的附件发送。感谢您的任何见解,谢谢。

var pdfFiles: [String] = []
var myPDFsArray : Array<MyPDFs> = []
var selectedRow : NSInteger? // optional NSInteger

@available(ios 8.0, *)
public func documentPicker(_ controller: UIDocumentPickerViewController, didPickDocumentAt url: URL) 

    let myURL = url as URL
    print("import result : \(myURL)")

    do 
        let data = try Data(contentsOf: myURL)
        print("data=\(data)")

    
    catch /* error handling here */

    let pathString = myURL.path // String path for PDF
    let PDFName = myURL.lastPathComponent // string for PDF Name

    if controller.documentPickerMode == UIDocumentPickerMode.import 
        DispatchQueue.main.async()
            self.myPDFsArray.append(MyPDFs(fileTitle: pathString, fileName: PDFName))

            
    
    print (pathString)
    print (PDFName)


@available(iOS 8.0, *)
public func documentMenu(_ documentMenu:UIDocumentMenuViewController, didPickDocumentPicker documentPicker: UIDocumentPickerViewController) 
    documentPicker.delegate = self
    present(documentPicker, animated: true, completion: nil)
    //self.present(documentPicker, animated: true, completion: nil)

func documentPickerWasCancelled(_ controller: UIDocumentPickerViewController) 
    print("we cancelled")

    dismiss(animated: true, completion: nil)


func documentMenuWasCancelled(documentMenu: UIDocumentMenuViewController) 
    print("menu got cancelled")
    documentMenu.dismiss(animated: true, completion: nil)



@IBAction func addButtonTapped(_ sender: Any)
    let importMenu = UIDocumentMenuViewController(documentTypes: [String(kUTTypePDF)], in: .import)
    importMenu.delegate = self
    importMenu.modalPresentationStyle = .formSheet
    self.present(importMenu, animated: true, completion: nil)
    //importMenu.addOption(withTitle: "Create New Document", image: nil, order: .first, handler: print("New Doc Requested"))
    insertNewFileTitle()


func insertNewFileTitle()
    if addFileTextField.text!.isEmpty 
        print("Add Video Text Field is empty")
    
    pdfFiles.append(addFileTextField.text!)

    let indexPath = IndexPath(row: pdfFiles.count - 1, section: 0)
    tableView.beginUpdates()
    tableView.insertRows(at: [indexPath], with: .automatic) //can customize
    tableView.reloadData()//reload table
    tableView.endUpdates()
    addFileTextField.text = ""
    view.endEditing(true)


func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int 
    return pdfFiles.count


func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell 
    let fileTitleCell = pdfFiles[indexPath.row]
    let cell = tableView.dequeueReusableCell(withIdentifier: "FileCell") as! FileCell
    cell.fileTitle.text = fileTitleCell

    if myPDFsArray.contains(MyPDFs(fileTitle: "fileTitle", fileName: "fileName"))

        cell.accessoryType = .checkmark
    

    else
        cell.accessoryType = .none
    
    return cell



func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) 
    selectedRow = indexPath.row // indexPath.row is the value of the row you tap on, starting from first 0
    tableView.deselectRow(at: indexPath, animated: true)
    if let cell = tableView.cellForRow(at: indexPath as IndexPath) 
        //selectedRow = indexPath.row // indexPath.row is the value of the row you tap on, starting from first 0
        //if myPDFsArray.contains(MyPDFs(fileTitle: "fileTitle", fileName: "fileName"))
        if cell.accessoryType == .checkmark
            cell.accessoryType = .none
            //myPDFsArray.remove(at: MyPDFs.index(ofAccessibilityElement: NSObject.self))

            //print(MyPDFs.init(fileTitle: "fileTitle", fileName: "fileName"))
            print("")
            print(myPDFsArray[indexPath.row].fileTitle!)
            print("")
            print(myPDFsArray[indexPath.row].fileName!)
        
        else
            cell.accessoryType = .checkmark
            selectedRow = indexPath.row
            myPDFsArray.append(MyPDFs(fileTitle: "fileTitle", fileName: "fileName"))
            //print(MyPDFs.init(fileTitle: "fileTitle", fileName: "fileName"))
            print("")
            print(myPDFsArray[selectedRow!].fileTitle!)
            print("")
            print(myPDFsArray[selectedRow!].fileName!)
        
        //
    

下一部分是我发送电子邮件的按钮操作

@IBAction func sendEmail(_sender: Any)      
    let subject = "subject"
    let messageBody = "pdf file names"
    lblValidationMessage.isHidden = true

    let allPaths = NSSearchPathForDirectoriesInDomains(.documentDirectory, .userDomainMask, true)
    let documentsDirectory = allPaths.first!
    let myPath = "/(MyPDFs[selectedRow].fileName)" //is it a forward slash or backslash? 
    let pathForFile = documentsDirectory.appending(myPath)
    print("")
    print(pathForFile)
    print("")

    guard let email = emailNew.text, emailNew.text?.characters.count != 0  else 
        lblValidationMessage.isHidden = false
        lblValidationMessage.text = "Please enter your email"
        return
    

    if isValidEmail(emailNew: email) == false 
        lblValidationMessage.isHidden = false
        lblValidationMessage.text = "Please enter a valid email address"
        return
    

    if( MFMailComposeViewController.canSendMail() ) 
        print("Can send email.")

        let mailComposer = MFMailComposeViewController()
        mailComposer.mailComposeDelegate = self

        //Set the subject and message of the email
        mailComposer.setToRecipients([email])
        mailComposer.setSubject(subject)
        mailComposer.setMessageBody(messageBody, ishtml: false)


        // Add attachment
        if let fileData = NSData(contentsOfFile: pathForFile) 
            print("file data loaded")
                mailComposer.addAttachmentData(fileData as Data, mimeType: "application/pdf", fileName: "fileName")
            

        //this will compose and present mail to user"
        self.present(mailComposer, animated: true, completion: nil)
     
    else 
        self.showSendMailErrorAlert()
    

【问题讨论】:

【参考方案1】:

我不确定我是否理解正确。为什么需要将 PDF 存储在 UITableView 单元格中?

为什么不直接创建这样的模型:

class MyPDFs : NSObject

    var fileTitle : String?
    var fileName : String?

    override init()

    convenience init(fileTitle : String , fileName : String)
    
        self.init()

        self.fileTitle = fileTitle
        self.fileName  = fileName
    

每次点击 addButton 时,都会创建一个新对象,将其附加到 MyPDFs 类型的数组中,然后重新加载表格。

var myPDFsArray : Array<MyPDFs> = []
myPDFsArray.append(MyPDFsObject)
myUITableView.reloadData()

这样,您可以在使用 indexPath.row 选择 UITableView 单元格时获取 PDF 属性,并且可以获取要附加到 MailComposer 的名称和文件路径。

【讨论】:

非常感谢您的洞察力。我能够创建一个模型来在导入 PDF 时存储它。现在,当我选择 UITableView 单元格时,我无法弄清楚如何获取 PDF 属性。我将更新我的代码以显示我到目前为止所拥有的内容。 由于您将所有 MyPDFsObjects 添加到相同类型的数组中,我通常在 didSelectRowAt 中尝试这样的操作: print(myPDFsArray[indexPath.row].fileTitle) print(myPDFsArray[indexPath.row ].fileName) myPDFsArray[indexPath.row] 基本上是 MyPDFs 类型的对象。 谢谢!当我选择单元格时,我的两个 url 字符串都会打印出来。虽然我不知道如何将所有选定的表行附加到 MailComposer。我可以在这里发布我的代码吗?或提交新问题? @Carlos27- 如果您愿意,可以在此处发布。不确定这是否违反 SO 规则。 好的我已经更新了我的代码以包含我的按钮操作来发送电子邮件。基本上,除了 addAttachment 函数外,我的一切工作正常。如何告诉 addAttachment 包含所有选中的选定文件?我已经将 urls 路径格式化为字符串,所以我只需要调用 tableview didSelectRowAt 吗?

以上是关于如何使用 UIDocumentPicker 将 pdf 文件导入表格视图单元格的主要内容,如果未能解决你的问题,请参考以下文章

无法使用 UIViewRepresentable 和 UIDocumentPicker 选择文件夹

使用自定义 UTI 删除 UIDocumentPicker 导入/导出

无法使用 UIDocumentPicker 导入页面和编号文档

从 UIDocumentPicker 下载文件并等待下载完成

快速在 UIDocumentPicker 中设置文档扩展名

UIDocumentPicker 导航栏按钮在 iOS 11 中隐藏