{"id":390,"date":"2017-04-05T06:10:01","date_gmt":"2017-04-05T06:10:01","guid":{"rendered":"http:\/\/inwizards.com\/blog\/?p=390"},"modified":"2026-01-02T14:15:06","modified_gmt":"2026-01-02T14:15:06","slug":"draw-digital-signature-ios-using-swift-2-0","status":"publish","type":"post","link":"https:\/\/www.inwizards.com\/blog\/draw-digital-signature-ios-using-swift-2-0\/","title":{"rendered":"How to Draw Digital Signatures in iOS Using Swift 5: A Developer\u2019s Tutorial"},"content":{"rendered":"<p>Digital signatures are essential for mobile apps that handle contracts, forms, or approvals. Whether you\u2019re building a banking app, a document management system, or a delivery app, enabling users to sign directly on their device enhances usability and compliance. In this tutorial, we\u2019ll show you how to implement <b>digital signature capture in iOS using Swift 5<\/b>, step by step.<\/p>\n<h2><b>Table of Contents<\/b><\/h2>\n<ol>\n<li aria-level=\"1\">Why Digital Signatures Matter<\/li>\n<li aria-level=\"1\">Project Setup in Xcode<\/li>\n<li aria-level=\"1\">Creating a Signature View<\/li>\n<li aria-level=\"1\">Integrating the Signature View in Your ViewController<\/li>\n<li aria-level=\"1\">Saving Signatures to Photos or PDF<\/li>\n<li aria-level=\"1\">Testing and Debugging<\/li>\n<li aria-level=\"1\">FAQs<\/li>\n<\/ol>\n<h3><b>Why Digital Signatures Matter<\/b><\/h3>\n<p>Digital signatures improve workflows by:<\/p>\n<ul>\n<li aria-level=\"1\">Eliminating the need for printing, signing, and scanning.<\/li>\n<li aria-level=\"1\">Reducing errors in document handling.<\/li>\n<li aria-level=\"1\">Increasing trust and compliance in mobile forms.<\/li>\n<\/ul>\n<p>In iOS, capturing a signature is straightforward using UIView for drawing, combined with UIImage for saving the results.<\/p>\n<h3><b>Project Setup in Xcode<\/b><\/h3>\n<ol>\n<li aria-level=\"1\">Open <b>Xcode<\/b> and create a new project.\n<ul>\n<li aria-level=\"2\">Template: <b>App<\/b><\/li>\n<li aria-level=\"2\">Language: <b>Swift<\/b><\/li>\n<li aria-level=\"2\">Interface: <b>Storyboard<\/b><\/li>\n<\/ul>\n<\/li>\n<li aria-level=\"1\">Name your project, e.g., DigitalSignatureDemo.<\/li>\n<li aria-level=\"1\">Ensure you select <b>iOS 14+<\/b> or later for modern Swift compatibility.<\/li>\n<\/ol>\n<h3><b>Creating a Signature View<\/b><\/h3>\n<p>We&#8217;ll create a custom UIView that tracks touches to draw a signature.<\/p>\n<h4><b>Step 1: Create a Swift file<\/b><\/h4>\n<ol>\n<li aria-level=\"1\">Go to <b>File \u2192 New \u2192 File \u2192 Swift File<\/b><\/li>\n<li aria-level=\"1\">Name it SignatureView.swift.<\/li>\n<\/ol>\n<h4><b>Step 2: Implement the drawing logic<\/b><\/h4>\n<p>import UIKit<\/p>\n<p>&nbsp;<\/p>\n<p>class SignatureView: UIView {<\/p>\n<p>&nbsp;<\/p>\n<p>private var lines: [Line] = []<\/p>\n<p>private var strokeColor: UIColor = .black<\/p>\n<p>private var lineWidth: CGFloat = 2.0<\/p>\n<p>&nbsp;<\/p>\n<p>required init?(coder: NSCoder) {<\/p>\n<p>super.init(coder: coder)<\/p>\n<p>self.backgroundColor = .white<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>override func touchesBegan(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {<\/p>\n<p>guard let touch = touches.first else { return }<\/p>\n<p>let newLine = Line(points: [touch.location(in: self)], color: strokeColor, width: lineWidth)<\/p>\n<p>lines.append(newLine)<\/p>\n<p>setNeedsDisplay()<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>override func touchesMoved(_ touches: Set&lt;UITouch&gt;, with event: UIEvent?) {<\/p>\n<p>guard let touch = touches.first, var lastLine = lines.popLast() else { return }<\/p>\n<p>lastLine.points.append(touch.location(in: self))<\/p>\n<p>lines.append(lastLine)<\/p>\n<p>setNeedsDisplay()<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>override func draw(_ rect: CGRect) {<\/p>\n<p>super.draw(rect)<\/p>\n<p>guard let context = UIGraphicsGetCurrentContext() else { return }<\/p>\n<p>context.setLineCap(.round)<\/p>\n<p>&nbsp;<\/p>\n<p>for line in lines {<\/p>\n<p>context.setStrokeColor(line.color.cgColor)<\/p>\n<p>context.setLineWidth(line.width)<\/p>\n<p>for (i, point) in line.points.enumerated() {<\/p>\n<p>if i == 0 { context.move(to: point) }<\/p>\n<p>else { context.addLine(to: point) }<\/p>\n<p>}<\/p>\n<p>context.strokePath()<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>func clear() {<\/p>\n<p>lines.removeAll()<\/p>\n<p>setNeedsDisplay()<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>func getSignatureImage() -&gt; UIImage {<\/p>\n<p>UIGraphicsBeginImageContextWithOptions(bounds.size, false, 0)<\/p>\n<p>drawHierarchy(in: bounds, afterScreenUpdates: true)<\/p>\n<p>let signature = UIGraphicsGetImageFromCurrentImageContext()!<\/p>\n<p>UIGraphicsEndImageContext()<\/p>\n<p>return signature<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>\/\/ Helper struct<\/p>\n<p>struct Line {<\/p>\n<p>var points: [CGPoint]<\/p>\n<p>var color: UIColor<\/p>\n<p>var width: CGFloat<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<h3><b>Integrating the Signature View in Your ViewController<\/b><\/h3>\n<ol>\n<li aria-level=\"1\">Open <b>Main.storyboard<\/b> and add a UIView.<\/li>\n<li aria-level=\"1\">Set its class to SignatureView in the Identity Inspector.<\/li>\n<li aria-level=\"1\">Add two UIButtons:\n<ul>\n<li aria-level=\"2\"><b>Clear<\/b> to reset the signature.<\/li>\n<li aria-level=\"2\"><b>Save<\/b> to save the signature image.<\/li>\n<\/ul>\n<\/li>\n<li aria-level=\"1\">Connect your IBOutlet and IBAction in ViewController.swift.<\/li>\n<\/ol>\n<p>import UIKit<\/p>\n<p>&nbsp;<\/p>\n<p>class ViewController: UIViewController {<\/p>\n<p>&nbsp;<\/p>\n<p>@IBOutlet weak var signatureView: SignatureView!<\/p>\n<p>@IBOutlet weak var imageView: UIImageView!<\/p>\n<p>&nbsp;<\/p>\n<p>@IBAction func clearSignature(_ sender: UIButton) {<\/p>\n<p>signatureView.clear()<\/p>\n<p>imageView.image = nil<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<p>@IBAction func saveSignature(_ sender: UIButton) {<\/p>\n<p>let signature = signatureView.getSignatureImage()<\/p>\n<p>imageView.image = signature<\/p>\n<p>UIImageWriteToSavedPhotosAlbum(signature, nil, nil, nil)<\/p>\n<p>}<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<h3><b>Saving Signatures to PDF (Optional)<\/b><\/h3>\n<p>You can also save the signature as a PDF for contracts or forms:<\/p>\n<p>func saveSignatureAsPDF(signature: UIImage) {<\/p>\n<p>let pdfData = NSMutableData()<\/p>\n<p>UIGraphicsBeginPDFContextToData(pdfData, CGRect(origin: .zero, size: signature.size), nil)<\/p>\n<p>UIGraphicsBeginPDFPage()<\/p>\n<p>signature.draw(in: CGRect(origin: .zero, size: signature.size))<\/p>\n<p>UIGraphicsEndPDFContext()<\/p>\n<p>&nbsp;<\/p>\n<p>let documentsPath = FileManager.default.urls(for: .documentDirectory, in: .userDomainMask).first!<\/p>\n<p>let pdfPath = documentsPath.appendingPathComponent(&#8220;signature.pdf&#8221;)<\/p>\n<p>pdfData.write(to: pdfPath, atomically: true)<\/p>\n<p>print(&#8220;Saved PDF to: \\(pdfPath)&#8221;)<\/p>\n<p>}<\/p>\n<p>&nbsp;<\/p>\n<h3><b>Testing and Debugging<\/b><\/h3>\n<ul>\n<li aria-level=\"1\">Run the app on <b>simulator<\/b> or a <b>real device<\/b>.<\/li>\n<li aria-level=\"1\">Draw your signature and verify it appears in UIImageView.<\/li>\n<li aria-level=\"1\">Test <b>clear<\/b> and <b>save<\/b> functionality.<\/li>\n<li aria-level=\"1\">For PDFs, check the Documents folder in the simulator or use Files app on a real device.<\/li>\n<\/ul>\n<h3><b>Developer Tips<\/b><\/h3>\n<ul>\n<li aria-level=\"1\">Adjust strokeColor and lineWidth for signature style.<\/li>\n<li aria-level=\"1\">Consider adding <b>undo functionality<\/b> by keeping a history stack of lines.<\/li>\n<li aria-level=\"1\">For production apps, secure signature storage and encryption may be required.<\/li>\n<li aria-level=\"1\">Optimize performance for large signature images by limiting the number of stored points.<\/li>\n<\/ul>\n<h3><b>FAQs<\/b><\/h3>\n<p><b>Q1: Can I capture signatures in SwiftUI?<\/b><b><br \/>\n<\/b>Yes! You can wrap SignatureView in UIViewRepresentable to use it in SwiftUI apps.<\/p>\n<p><b>Q2: How do I add multiple pages for signatures in PDF?<\/b><b><br \/>\n<\/b>Use UIGraphicsBeginPDFPage() for each page and draw signatures separately.<\/p>\n<p><b>Q3: How to export signatures to cloud storage?<\/b><b><br \/>\n<\/b>Convert the signature image to Data using pngData() or jpegData() and upload to Firebase, AWS S3, or your preferred backend.<\/p>\n<p><b>Q4: Can I customize the pen color and thickness?<\/b><b><br \/>\n<\/b>Yes! Modify strokeColor and lineWidth in SignatureView. You can add a UI picker for dynamic selection.<\/p>\n<p><b>Q5: How to optimize for large screen devices like iPad?<\/b><b><br \/>\n<\/b>Scale the drawing points relative to the bounds.size to maintain proportionality on all devices.<\/p>\n<h3><b>Conclusion<\/b><\/h3>\n<p>Capturing digital signatures in iOS is simple and highly practical for modern apps. By using a custom UIView and Swift 5, you can build a <b>robust, reusable, and customizable signature feature<\/b>. This tutorial equips you with the core functionality, plus optional PDF export for real-world applications.<\/p>\n<p><b>CTA:<\/b> Ready to add digital signature functionality to your app? Try this Swift 5 implementation and integrate it with your forms or contracts today!<\/p>\n","protected":false},"excerpt":{"rendered":"<p>Digital signatures are essential for mobile apps that handle contracts, forms, or approvals. Whether you\u2019re building a banking app, a document management system, or a delivery app, enabling users to sign directly on their device enhances usability and compliance. In<\/p>\n","protected":false},"author":1,"featured_media":391,"comment_status":"open","ping_status":"open","sticky":false,"template":"","format":"standard","meta":{"_monsterinsights_skip_tracking":false,"_monsterinsights_sitenote_active":false,"_monsterinsights_sitenote_note":"","_monsterinsights_sitenote_category":0,"spay_email":""},"categories":[1],"tags":[],"jetpack_featured_media_url":"https:\/\/i0.wp.com\/www.inwizards.com\/blog\/wp-content\/uploads\/2017\/04\/pizap.com14913723754261.jpg?fit=1023%2C433&ssl=1","_links":{"self":[{"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/posts\/390"}],"collection":[{"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/posts"}],"about":[{"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/types\/post"}],"author":[{"embeddable":true,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/users\/1"}],"replies":[{"embeddable":true,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/comments?post=390"}],"version-history":[{"count":5,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/posts\/390\/revisions"}],"predecessor-version":[{"id":3492,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/posts\/390\/revisions\/3492"}],"wp:featuredmedia":[{"embeddable":true,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/media\/391"}],"wp:attachment":[{"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/media?parent=390"}],"wp:term":[{"taxonomy":"category","embeddable":true,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/categories?post=390"},{"taxonomy":"post_tag","embeddable":true,"href":"https:\/\/www.inwizards.com\/blog\/wp-json\/wp\/v2\/tags?post=390"}],"curies":[{"name":"wp","href":"https:\/\/api.w.org\/{rel}","templated":true}]}}