توليد تقارير PDF بلغة Swift لنظامي iOS وmacOS
يعد إنشاء مستندات PDF من المهام الشائعة في تطبيقات الأجهزة المحمولة وأجهزة الكمبيوتر المكتبية. على منصات Apple (iOS, macOS)، تتوفر أدوات مدمجة قوية لذلك: PDFKit وCore Graphics. في هذه المقالة، سنشرح كيفية إنشاء تقرير متعدد الصفحات يحتوي على جداول ونصوص ورسومات باستخدام Swift الأصلي فقط.
لماذا نستخدم الأدوات المدمجة؟
- لا تتطلب تبعيات خارجية — كل شيء مضمن بالفعل في SDK.
- تحكم كامل في العرض — العمل مع الإحداثيات والخطوط والألوان.
- توافق عبر المنصات — يعمل الكود على كل من iOS وmacOS.
- أداء عالٍ — يستخدم Core Graphics تسريع الأجهزة.
الأساليب الأساسية
هناك طريقتان رئيسيتان لتوليد PDF في Swift:
- PDFKit — واجهة برمجة تطبيقات عالية المستوى للعمل مع PDF (قراءة، تحرير، إنشاء).
- Core Graphics — عرض منخفض المستوى عبر سياق PDF.
سننظر في الطريقة الثانية لأنها توفر أقصى مرونة عند إنشاء التقارير "من الصفر".
إنشاء سياق PDF
الخطوة الأولى هي إنشاء سياق PDF سنرسم فيه العناصر. لهذا، نستخدم الدالة UIGraphicsBeginPDFContextToFile (لنظام iOS) أو ما يعادلها لنظام macOS.
import UIKit
func generatePDF() -> URL? { let fileName = "Report.pdf" let paths = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask) guard let documentsURL = paths.first else { return nil } let pdfURL = documentsURL.appendingPathComponent(fileName) let pageSize = CGRect(x: 0, y: 0, width: 612, height: 792) // A4 UIGraphicsBeginPDFContextToFile(pdfURL.path, pageSize, nil) // هنا سنرسم الصفحات UIGraphicsEndPDFContext() return pdfURL}إضافة الصفحات والمحتوى
تبدأ كل صفحة باستدعاء UIGraphicsBeginPDFPage(). بعد ذلك، يمكن استخدام طرق UIKit القياسية للرسم.
func drawReport() { guard let pdfURL = generatePDF() else { return } UIGraphicsBeginPDFContextToFile(pdfURL.path, CGRect(x: 0, y: 0, width: 612, height: 792), nil) // الصفحة الأولى UIGraphicsBeginPDFPage() drawHeader(title: "التقرير الشهري") drawTable(data: sampleData) // الصفحة الثانية (إذا لزم الأمر) UIGraphicsBeginPDFPage() drawChart() UIGraphicsEndPDFContext()}رسم النصوص والعناوين
لرسم النص، نستخدم NSString مع السمات.
func drawHeader(title: String) { let titleAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 24), .foregroundColor: UIColor.darkGray ] title.draw(at: CGPoint(x: 50, y: 40), withAttributes: titleAttributes)}إنشاء جدول بسيط
يمكن رسم الجدول باستخدام الخطوط والنصوص. فيما يلي مثال لتوليد جدول بعمودين.
func drawTable(data: [(String, String)]) { let startX: CGFloat = 50 var startY: CGFloat = 100 let colWidth: CGFloat = 250 let rowHeight: CGFloat = 30 // رسم العناوين let headerAttributes: [NSAttributedString.Key: Any] = [ .font: UIFont.boldSystemFont(ofSize: 14), .foregroundColor: UIColor.black ] "الاسم".draw(at: CGPoint(x: startX, y: startY), withAttributes: headerAttributes) "القيمة".draw(at: CGPoint(x: startX + colWidth, y: startY), withAttributes: headerAttributes) startY += rowHeight // رسم الصفوف for (key, value) in data { let rowAtt