PDFKit - Wrapping text

Dear all, I have an app in which I'm trying to create a pdf from the data stored. Everything is working fine except the fact that the text is not following the page margins, going out of the page of being truncated without being written on the line below.

Has anybody experienced the same in the past?

Please assist, I'm getting out of my mind with this in the last two days... Here the code of the function which is creating the PDF.

        let pdfMetaData = [
            kCGPDFContextCreator: "Your App Name",
            kCGPDFContextAuthor: "Your Name",
            kCGPDFContextTitle: "Allenamento"
        ]
        let pageWidth = 8.5 * 72.0  // Standard letter size in points (8.5 x 11 inches)
        let pageHeight = 11 * 72.0
        let pageSize = CGRect(x: 0, y: 0, width: pageWidth, height: pageHeight)
        let margin: CGFloat = 20.0

        let pdfData = NSMutableData()
        guard let consumer = CGDataConsumer(data: pdfData as CFMutableData) else {
            print("Errore nella creazione del consumer")
            return
        }
        var mediaBox = pageSize
        guard let pdfContext = CGContext(consumer: consumer, mediaBox: &mediaBox, pdfMetaData as CFDictionary) else {
            print("Errore nella creazione del contesto PDF")
            return
        }

        pdfContext.beginPDFPage(nil)
        
        // Parte superiore della pagina
        ...

        // Disegno del rettangolo "MATERIALE DA ALLENAMENTO"
        ...

        // Disegno del rettangolo "ESERCITAZIONI ALLENAMENTO"
        let exercisesRect = CGRect(x: margin, y: cellYPosition - 45, width: pageWidth - 2 * margin, height: 25)
        pdfContext.setFillColor(NSColor.lightGray.cgColor)
        pdfContext.fill(exercisesRect)
        pdfContext.setStrokeColor(NSColor.black.cgColor)
        pdfContext.stroke(exercisesRect)
        
        let exercisesText = "ESERCITAZIONI ALLENAMENTO"
        let exercisesAttributedString = NSAttributedString(string: exercisesText, attributes: boldAttributes)
        let exercisesTextPosition = CGPoint(x: exercisesRect.midX - exercisesAttributedString.size().width / 2, y: exercisesRect.midY - 5)
        drawText(attributedString: exercisesAttributedString, position: exercisesTextPosition, context: pdfContext)
        
        // Iniziamo a disegnare le informazioni degli esercizi
        let sortedExercises = training.trainingExercises.sorted { $0.order < $1.order }
        var currentY = exercisesRect.minY - 30

        for trainingExercise in sortedExercises {
            // Gestione del wrap text e posizionamento su più pagine
            let remainingHeight = currentY - margin
            if remainingHeight < 100 {
                pdfContext.endPDFPage()
                pdfContext.beginPDFPage(nil)
                currentY = pageHeight - margin
            }

            // Disegna la durata
            let durationText = "\(trainingExercise.duration) min"
            let durationAttributedString = NSAttributedString(string: durationText, attributes: boldAttributes)
            drawText(attributedString: durationAttributedString, position: CGPoint(x: margin, y: currentY), context: pdfContext)
            currentY -= 20
            
            // Disegna la descrizione con wrap text
            let descriptionText = trainingExercise.exercise.exerciseDescription
            let descriptionAttributedString = NSAttributedString(string: descriptionText, attributes: regularAttributes)
            
            let maxTextWidth = pageWidth - 2 * margin
            let descriptionBoundingBox = descriptionAttributedString.boundingRect(with: CGSize(width: maxTextWidth, height: .greatestFiniteMagnitude), options: [.usesLineFragmentOrigin, .usesFontLeading])
            
            if currentY - descriptionBoundingBox.height < margin {
                pdfContext.endPDFPage()
                pdfContext.beginPDFPage(nil)
                currentY = pageHeight - margin
            }
            
            // Disegno della descrizione con supporto per il wrap text
            let descriptionFramesetter = CTFramesetterCreateWithAttributedString(descriptionAttributedString)
            let descriptionPath = CGPath(rect: CGRect(x: margin, y: currentY - descriptionBoundingBox.height, width: maxTextWidth, height: descriptionBoundingBox.height), transform: nil)
            let descriptionFrame = CTFramesetterCreateFrame(descriptionFramesetter, CFRangeMake(0, 0), descriptionPath, nil)
            CTFrameDraw(descriptionFrame, pdfContext)

            currentY -= descriptionBoundingBox.height + 10
            
            // Disegna l'immagine sotto la descrizione
            if let imagePath = trainingExercise.exercise.imagePath, let image = NSImage(contentsOfFile: imagePath) {
                let imageCG = image.cgImage(forProposedRect: nil, context: nil, hints: nil)
                let imageAspect = CGFloat(imageCG!.width) / CGFloat(imageCG!.height)
                let targetWidth = min(maxTextWidth, CGFloat(400))
                let targetHeight = targetWidth / imageAspect
                
                if currentY - targetHeight < margin {
                    pdfContext.endPDFPage()
                    pdfContext.beginPDFPage(nil)
                    currentY = pageHeight - margin
                }

                let imageTargetRect = CGRect(x: margin, y: currentY - targetHeight, width: targetWidth, height: targetHeight)
                pdfContext.draw(imageCG!, in: imageTargetRect)
                currentY -= targetHeight + 10
            }

            // Disegna una linea sottile come separatore
            pdfContext.setStrokeColor(NSColor.lightGray.cgColor)
            pdfContext.setLineWidth(1.0)
            let lineYPosition = currentY - 5
            pdfContext.move(to: CGPoint(x: margin, y: lineYPosition))
            pdfContext.addLine(to: CGPoint(x: pageWidth - margin, y: lineYPosition))
            pdfContext.strokePath()

            currentY -= 20  // Spazio tra esercizi
        }

        pdfContext.endPDFPage()
        pdfContext.closePDF()

        let dateFormatter = DateFormatter()
        dateFormatter.dateFormat = "yyyy-MM-dd"
        let fileName = "Allenamento_\(dateFormatter.string(from: training.date)).pdf"
        
        if let documentsURL = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first {
            let fileURL = documentsURL.appendingPathComponent(fileName)
            
            do {
               ...
                }
            } catch {
                print("Errore durante il salvataggio del PDF: \(error)")
            }
        }
    }

    private func drawText(attributedString: NSAttributedString, position: CGPoint, context: CGContext) {
        let line = CTLineCreateWithAttributedString(attributedString)
        context.textPosition = position
        CTLineDraw(line, context)
    }
PDFKit - Wrapping text
 
 
Q