Swift — автоматическое сохранение PDF-файла в приложении «Файлы» на моем iPhone

Я отчаянно нуждаюсь в помощи.

Я пытаюсь создать приложение, которое позволяет пользователю сохранять файл PDF по ссылке, такой как пример, который я дал в массиве subjectLinks, все эти ссылки указывают на страницу PDF, и я пытаюсь загрузить его и сохранить в мое приложение. До сих пор я искал везде и нашел способ сделать это с помощью приложения «Файлы», поэтому в коде я загружаю данные pdf и открываю его с помощью UIDocument и PresentPreview для его отображения, и мне удалось разрешить пользователю поделиться загруженным файлом и также сохранить его в «Файлы».

Однако проблема возникает, поскольку я хочу сделать так, чтобы, когда пользователь нажимал «Загрузить», файл автоматически сохранялся в приложении «Файлы» в каталоге, чтобы пользователю не нужно было нажимать кнопку выбора, затем выбирать «Сохранить в файлы», а затем искать где сохранить. Это возможно??

Если это невозможно, по крайней мере, когда пользователь выбирает кнопку выбора и нажимает «Сохранить в файлы», он автоматически создает отдельный каталог, в котором пользователь может видеть и сохранять PDF-файл?

Я хочу сделать это, как и в большинстве случаев, когда выбрано «Сохранить в файлы», сохранение «На моем iPhone» недоступно, так как нет каталога или чего-то подобного, поэтому его можно сохранить только на диск Google или iCloud Drive, и это является основным неудобство.

Простите за длинный пост. НО БУДУ ОЧЕНЬ БЛАГОДАРЕН, ЕСЛИ КТО-ТО МОЖЕТ ПОМОЧЬ РЕШИТЬ МОЮ ПРОБЛЕМУ. ЗАРАНЕЕ ОГРОМНОЕ СПАСИБО :)

P.S. Пока все в моем коде работает отлично, просто я совершенно не понимаю, как реализовать функции, описанные выше?

import UIKit
import StoreKit

class TableViewController: UITableViewController {

let documentInteractionController = UIDocumentInteractionController()

let subjectLinks = ["https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Accounting%20(9706)/2015%20Jun/9706_s15_qp_42.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Economics%20(9708)/2017%20Jun/9708_s17_qp_12.pdf", "https://pastpapers.papacambridge.com/Cambridge%20International%20Examinations%20(CIE)/AS%20and%20A%20Level/Mathematics%20(9709)/2018-May-June/9709_s18_qp_12.pdf"]

override func viewDidLoad() {
    super.viewDidLoad()
    documentInteractionController.delegate = self as? UIDocumentInteractionControllerDelegate
}

override func didReceiveMemoryWarning() {
    super.didReceiveMemoryWarning()
}

override func numberOfSections(in tableView: UITableView) -> Int {
    return 1
}

override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
    return subjectLinks.count
}

override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
    let cell = tableView.dequeueReusableCell(withIdentifier: "Cell", for: indexPath)
    cell.textLabel?.text = subjectLinks[indexPath.row]
    return cell
}

override func tableView(_ tableView: UITableView, editActionsForRowAt indexPath: IndexPath) -> [UITableViewRowAction]?
{
    // 1
    let shareAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Download" , handler: { (action:UITableViewRowAction, indexPath: IndexPath) -> Void in
        // 2
        let downloadMenu = UIAlertController(title: nil, message: "Download this paper", preferredStyle: .actionSheet)

        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)

        downloadMenu.addAction(UIAlertAction(title: "Download", style: UIAlertActionStyle.destructive, handler: { action in self.storeAndShare(withURLString: self.subjectLinks[indexPath.row])}))
        downloadMenu.addAction(cancelAction)

        self.present(downloadMenu, animated: true, completion: nil)
    })
    // 3
    let rateAction = UITableViewRowAction(style: UITableViewRowActionStyle.default, title: "Rate" , handler: { (action:UITableViewRowAction, indexPath:IndexPath) -> Void in
        // 4
        let rateMenu = UIAlertController(title: nil, message: "Rate this App", preferredStyle: .actionSheet)

        let appRateAction = UIAlertAction(title: "Rate", style: UIAlertActionStyle.default, handler: {action in SKStoreReviewController.requestReview()})
        let cancelAction = UIAlertAction(title: "Cancel", style: UIAlertActionStyle.cancel, handler: nil)

        rateMenu.addAction(appRateAction)
        rateMenu.addAction(cancelAction)

        self.present(rateMenu, animated: true, completion: nil)
    })
    // 5
    return [shareAction,rateAction]
}

}
    extension TableViewController {
    /// This function will set all the required properties, and then provide a preview for the document
    func share(url: URL) {
        documentInteractionController.url = url
        documentInteractionController.uti = url.typeIdentifier ?? "public.data, public.content"
        documentInteractionController.name = url.localizedName ?? url.lastPathComponent
        documentInteractionController.presentPreview(animated: true)
    }

    /// This function will store your document to some temporary URL and then provide sharing, copying, printing, saving options to the user
    func storeAndShare(withURLString: String) {
        guard let url = URL(string: withURLString) else { return }
        /// START YOUR ACTIVITY INDICATOR HERE
        URLSession.shared.dataTask(with: url) { data, response, error in
            guard let data = data, error == nil else { return }
            let fileManager = FileManager.default
            do {
                let documentDirectory = try fileManager.url(for: .documentDirectory, in: .userDomainMask, appropriateFor:nil, create:false)
                let fileURL = documentDirectory.appendingPathComponent("fileName.pdf")
                try data.write(to: fileURL)

                DispatchQueue.main.async {
                    self.share(url: fileURL)
                }
            } catch {
                print(error)
            }
            }.resume()
    }
}
extension TableViewController: UIDocumentInteractionControllerDelegate {
    /// If presenting atop a navigation stack, provide the navigation controller in order to animate in a manner consistent with the rest of the platform
    func documentInteractionControllerViewControllerForPreview(_ controller: UIDocumentInteractionController) -> UIViewController {
        guard let navVC = self.navigationController else {
            return self
        }
        return navVC
    }
}

person Danesh    schedule 12.09.2018    source источник
comment
Сохранение файла без согласия пользователя? Ты меня пугаешь.   -  person El Tomato    schedule 12.09.2018
comment
хахаха @ElTomato, не беспокойтесь, он сохраняет его только тогда, когда пользователь нажимает «Загрузить» и выбирает его сохранение, он просто делает это автоматически в место, где пользователю не нужно его выбирать.   -  person Danesh    schedule 12.09.2018


Ответы (1)


Пример загрузки любого pdf-файла и автоматического сохранения в папке с файлами iPhone.

    let urlString = "https://www.tutorialspoint.com/swift/swift_tutorial.pdf"
    let url = URL(string: urlString)
    let fileName = String((url!.lastPathComponent)) as NSString
    //Mark:  Create destination URL
    let documentsUrl:URL =  (FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first as URL?)!
    let destinationFileUrl = documentsUrl.appendingPathComponent("\(fileName)")
    //Mark: Create URL to the source file you want to download
    let fileURL = URL(string: urlString)
    let sessionConfig = URLSessionConfiguration.default
    let session = URLSession(configuration: sessionConfig)
    let request = URLRequest(url:fileURL!)
    let task = session.downloadTask(with: request) { (tempLocalUrl, response, error) in
        if let tempLocalUrl = tempLocalUrl, error == nil {
            //Mark: Success
            if let statusCode = (response as? HTTPURLResponse)?.statusCode {
                print("Successfully downloaded. Status code: \(statusCode)")
            }
            do {
                try FileManager.default.copyItem(at: tempLocalUrl, to: destinationFileUrl)
                do {
                    //Mark: Show UIActivityViewController to save the downloaded file
                    let contents  = try FileManager.default.contentsOfDirectory(at: documentsUrl, includingPropertiesForKeys: nil, options: .skipsHiddenFiles)
                    for indexx in 0..<contents.count {
                        if contents[indexx].lastPathComponent == destinationFileUrl.lastPathComponent {
                            let activityViewController = UIActivityViewController(activityItems: [contents[indexx]], applicationActivities: nil)
                            self.present(activityViewController, animated: true, completion: nil)
                        }
                    }
                }
                catch (let err) {
                    print("error: \(err)")
                }
            } catch (let writeError) {
                print("Error creating a file \(destinationFileUrl) : \(writeError)")
            }
        } else {
            print("Error took place while downloading a file. Error description: \(error?.localizedDescription ?? "")")
        }
    }
    task.resume()
    
    
person iOSDev    schedule 24.02.2021
comment
Файл уже существует, всегда отображается - person Ravish Kumar; 27.07.2021