おそらくですが、PKCanvasView
が再作成されていることが原因だと思います。
対策はstatic
変数とすることで、PKCanvasView
のインスタンスは変わらないようにします。ただし、そのままだとPDF読み込み後にパレット(PKToolPicker
)が消えてしまうので、都度、becomeFirstResponder()
するようにしています。
綺麗とは言えないですが、期待通りの動きになっていると思います。
import SwiftUI
import PDFKit
import PencilKit
import UniformTypeIdentifiers
struct PDFViewContainer: UIViewRepresentable {
@Binding var pdfDocument: PDFDocument?
func makeUIView(context: Context) -> PDFView {
let pdfView = PDFView()
pdfView.autoScales = true //pdfの拡大率を調整
pdfView.displayMode = .singlePage //表示モード
return pdfView
}
func updateUIView(_ uiView: PDFView, context: Context) {
uiView.document = pdfDocument
}
}
struct PKCanvasViewRepresentable: UIViewRepresentable {
private static var pkcView = PKCanvasView()
private static var toolPicker = PKToolPicker()
typealias UIViewType = PKCanvasView
func makeUIView(context: Context) -> PKCanvasView {
configureCanvasView(PKCanvasViewRepresentable.pkcView)
return PKCanvasViewRepresentable.pkcView
}
func updateUIView(_ uiView: PKCanvasView, context: Context) {
}
func configureCanvasView(_ canvasView: PKCanvasView) {
canvasView.drawingPolicy = .anyInput
PKCanvasViewRepresentable.toolPicker.addObserver(canvasView) //変化を検知
PKCanvasViewRepresentable.toolPicker.setVisible(true, forFirstResponder: canvasView) //表示
canvasView.becomeFirstResponder() //変化を適応させる
canvasView.isOpaque = false
}
static func becomeFirstResponder() {
PKCanvasViewRepresentable.pkcView.becomeFirstResponder()
}
}
struct ContentView: View {
@State private var pdfDocument: PDFDocument?
@State private var isDocumentPickerPresented = false
var body: some View {
ZStack {
// PDFViewを追加
PDFViewContainer(pdfDocument: $pdfDocument)
.frame(maxWidth: .infinity, maxHeight: .infinity)
// PKCanvasViewを重ねて描画する
PKCanvasViewRepresentable()
}
VStack {
Button("PDFファイルを選択") {
isDocumentPickerPresented = true
}
.padding()
}
.onChange(of: pdfDocument) {
PKCanvasViewRepresentable.becomeFirstResponder()
}
.fileImporter(
isPresented: $isDocumentPickerPresented,
allowedContentTypes: [UTType.pdf],
onCompletion: { result in
switch result {
case .success(let url):
//ファイルへのアクセス許可
guard url.startAccessingSecurityScopedResource() else {
// Handle the failure here.
print("startAccessingSecurityScopedResource error")
return
}
// PDFDocumentの作成
if let document = PDFDocument(url: url) {
print("PDFドキュメントが正常に読み込まれました")
self.pdfDocument = document
} else {
let error = NSError(domain: "com.example.PDFApp", code: 1, userInfo: [NSLocalizedDescriptionKey: "PDFドキュメントの読み込みに失敗しました"])
print("エラー: \(error.localizedDescription), \(error.localizedFailureReason ?? "")")
}
url.stopAccessingSecurityScopedResource()
case .failure(let error):
print("ファイル選択時にエラーが発生しました:\(error.localizedDescription)")
}
}
)
}
}