Warning: file_get_contents(/data/phpspider/zhask/data//catemap/9/ios/112.json): failed to open stream: No such file or directory in /data/phpspider/zhask/libs/function.php on line 167

Warning: Invalid argument supplied for foreach() in /data/phpspider/zhask/libs/tag.function.php on line 1116

Notice: Undefined index: in /data/phpspider/zhask/libs/function.php on line 180

Warning: array_chunk() expects parameter 1 to be array, null given in /data/phpspider/zhask/libs/function.php on line 181
Ios 从pdf数据中提取单个页面(或页面范围),而不加载整个pdf(有时需要太多RAM)_Ios_Swift_Pdf - Fatal编程技术网

Ios 从pdf数据中提取单个页面(或页面范围),而不加载整个pdf(有时需要太多RAM)

Ios 从pdf数据中提取单个页面(或页面范围),而不加载整个pdf(有时需要太多RAM),ios,swift,pdf,Ios,Swift,Pdf,在swift中使用PDFKit,可以使用PDFDocument打开pdf文件。 这很容易,而且效果很好。但我正在构建一个适合我需要的自定义pdf查看器(用于漫画书pdf),我有一个问题。在查看器中,我不需要将整个pdf文件存储在内存中。我一次只需要几页 此外,PDF仅由图像组成。没有文本或任何东西 当实例化PDFDocument时,整个pdf数据将加载到内存中。如果你有非常大的pdf文件(超过1GB),这不是最佳的(并且可能会在某些设备上崩溃)。据我所知,PDFKit无法只加载pdf文档的一部分

在swift中使用
PDFKit
,可以使用
PDFDocument
打开pdf文件。
这很容易,而且效果很好。但我正在构建一个适合我需要的自定义pdf查看器(用于漫画书pdf),我有一个问题。在查看器中,我不需要将整个pdf文件存储在内存中。我一次只需要几页

此外,PDF仅由图像组成。没有文本或任何东西

当实例化
PDFDocument
时,整个pdf数据将加载到内存中。如果你有非常大的pdf文件(超过1GB),这不是最佳的(并且可能会在某些设备上崩溃)。据我所知,PDFKit无法只加载pdf文档的一部分

对此我能做些什么吗?我还没有找到一个swift/obj-c库可以做到这一点(尽管我真的不知道搜索它的正确关键字)

我的解决方法是使用
FileManager
预处理PDF并将每个页面保存为.documents控制器(或类似工具)中的图像。这将产生大量文件,但会解决内存问题。不过,我不确定我是否喜欢这种方法

更新:

所以我按照@Prcela和@Sahil Manchanda的建议做了。它现在似乎在起作用

@嗯,那确实是个问题。当只有图像时会发生这种情况吗?pdf中没有任何其他内容

@Carpsen90:它们是本地的(保存在文档目录中)


编辑:我没有接受下面的答案,也没有给它赏金。这是自动的。这并不能解决问题。它仍然会将整个PDF加载到内存中

我有一个想法,你可以在PDFKit中实现这一点。阅读文档后,有一个功能允许选择某些页面。如果将其添加到collectionFlowView中,这可能会解决您的问题

func selection(from startPage: PDFPage, atCharacterIndex startCharacter: Int, to endPage: PDFPage, atCharacterIndex endCharacter: Int) -> PDFSelection?
然而,正如我所读到的,您主要拥有图像,还有另一个函数允许根据CG点提取pdf的部分内容:

func selection(from startPage: PDFPage, at startPoint: CGPoint, to endPage: PDFPage, at endPoint: CGPoint) -> PDFSelection?
也可以看看这个:

因为如果您只想查看页面而不想编辑任何注释等,那么这可能就是您所需要的

我还准备了一些代码来提取下面的一页。希望能有帮助

import PDFKit
import UIKit

class PDFViewController: UIViewController {

    override func viewDidLoad() {
        super.viewDidLoad()

        guard let url = Bundle.main.url(forResource: "myPDF", withExtension: "pdf") else {fatalError("INVALID URL")}
        let pdf = PDFDocument(url: url)
        let page = pdf?.page(at: 10) // returns a PDFPage instance
        // now you have one page extracted and you can play around with it.
    }
}
编辑1: 看看这个代码提取。我知道整个PDF都会被加载,但是这种方法可能会更节省内存,因为在PDFView中,iOS可能会更好地处理它:

func readBook() {

if let oldBookView = self.view.viewWithTag(3) {
    oldBookView.removeFromSuperview()
    // This removes the old book view when the user chooses a new book language
}

if #available(iOS 11.0, *) {
    let pdfView: PDFView = PDFView()
    let path = BookManager.getBookPath(bookLanguageCode: book.bookLanguageCode)
    let url = URL(fileURLWithPath: path)
    if let pdfDocument = PDFDocument(url: url) {
        pdfView.displayMode = .singlePageContinuous
        pdfView.autoScales = true
        pdfView.document = pdfDocument
        pdfView.tag = 3 // I assigned a tag to this view so that later on I can easily find and remove it when the user chooses a new book language
        let lastReadPage = getLastReadPage()

        if let page = pdfDocument.page(at: lastReadPage) {
            pdfView.go(to: page)
            // Subscribe to notifications so the last read page can be saved
            // Must subscribe after displaying the last read page or else, the first page will be displayed instead
            NotificationCenter.default.addObserver(self, selector: #selector(self.saveLastReadPage),name: .PDFViewPageChanged, object: nil)
        }
    }

    self.containerView.addSubview(pdfView)
    setConstraints(view: pdfView)
    addTapGesture(view: pdfView)
}
编辑2:这不是OP想要的答案。这也会将整个pdf加载到内存中。
阅读评论

也许这会有所帮助。看看苏拉尼简单的回答:这是一个有趣的想法。我会调查一下,看看这对我来说是否可行。非常感谢。“在查看器中,我不需要将整个pdf文件存储在内存中。”事实上,除非pdf被线性化,否则您需要。非线性化PDF可能在第100页中定义了第1页所需的对象,并且文件的所有对象也可能压缩在单个容器对象中。线性化PDF的设计是逐步加载,而不是将其保存为图像。您可以根据章节将pdf拆分为多个小pdf。这样一来,文件数量就会减少,您可以有效地使用PDFKit。PDF是本地的吗?还是必须远程加载它们?
让pdf=PDFDocument(url:url)
。这仍然会将整个pdf加载到内存中,这是我想要避免的。从文档中抓取页面不是问题。您是否尝试过在web视图中打开PDF以查看它是否提供类似的结果?这里是一个教程,在我的情况下,web视图不起作用。而且,到目前为止,我尝试过的所有苹果默认的pdf查看类都非常糟糕。web视图可能使用相同的技术来呈现pdf,这真的很糟糕。我会给CocoaPods一个镜头或GitHub搜索,也许这可以帮助您实现这一点。没有什么真正适合我的。