With PDFKit in SwiftUI, I'm using the findString
function to search the text of a PDF. That part works correctly, but when I use the extend
function to get some of the text on both sides of the found word (ie, its context in the page), it doesn't extend.
Am I doing this wrong? There is very little documentation or examples about the extend
function; even the Apple page doesn't specify what the units refer to in the extend call (presumably it means characters, but I suppose it could also be pixels, or some other measurement specific to PDFs).
Here is the code, and pictures of the app, the output (showing that the code can read all the text on the page), and the Acrobat Reader effect I'm trying to achieve.
If the extend
function truly is broken, and not just a problem in how I'm going about this, a workaround would be to use the text from the entire page, and extract the surrounding words from there, but that does get complicated, especially if there are multiple instances of the word on the page, or if the result straddles 2 pages.
import PDFKit
import SwiftUI
struct ContentView: View {
@StateObject var controller = PDFViewController()
@State var searchResults:[PDFSelection] = []
var body: some View {
VStack {
Button {
searchResults = controller.pdfView!.document!.findString("is", withOptions: [.caseInsensitive])
let fullPageText = controller.pdfView!.document!.string
print(fullPageText)
for result in searchResults {
let beforeExtending = result.string ?? ""
print("Before: \(beforeExtending)")
result.extend(atEnd: 3)
result.extend(atStart: 3)
let afterExtending = result.string ?? ""
print("After: \(afterExtending)")
}
} label: {
Text("Do search")
}
PDFKitView(url: generateURL(), controller: controller)
}
.padding()
}
func generateURL() -> URL {
let bundlePathRootAsString = Bundle.main.resourcePath!
var pdfPathInBundle = URL(fileURLWithPath: bundlePathRootAsString)
pdfPathInBundle.append(path: "TestPDF.pdf")
return pdfPathInBundle
}
}
struct PDFKitView: UIViewRepresentable {
func updateUIView(_ uiView: PDFView, context: Context) {
}
let url: URL
@ObservedObject var controller: PDFViewController
func makeUIView(context: Context) -> PDFView {
let pdfView = PDFView()
pdfView.document = PDFDocument(url: self.url)
pdfView.autoScales = true
controller.pdfView = pdfView
return pdfView
}
}
class PDFViewController: ObservableObject {
var pdfView: PDFView?
}