From 303db2ba7f6e75dc161ad649a37e31080ec722e2 Mon Sep 17 00:00:00 2001 From: GJ Nilsen Date: Wed, 3 May 2017 08:44:07 +0200 Subject: [PATCH 1/3] Small update, adding optional delegate methods and updating project files. Source is still backwards compatible. --- LICENSE | 2 +- README.md | 8 +- .../SignatureTest.xcodeproj/project.pbxproj | 22 ++-- SignatureTest/SignatureTest/AppDelegate.swift | 8 +- SignatureTest/SignatureTest/Info.plist | 4 +- .../SignatureTest/ViewController.swift | 33 ++++-- .../SignatureTest/YPDrawSignatureView.swift | 56 +++++++--- .../SignatureTestTests.swift | 36 ------ .../SignatureViewTest.swift | 104 ++++++++++++++++++ Sources/YPDrawSignatureView.swift | 48 +++++--- 10 files changed, 231 insertions(+), 90 deletions(-) delete mode 100644 SignatureTest/SignatureTestTests/SignatureTestTests.swift create mode 100644 SignatureTest/SignatureTestTests/SignatureViewTest.swift diff --git a/LICENSE b/LICENSE index 9d7db86..f17ee8d 100644 --- a/LICENSE +++ b/LICENSE @@ -1,6 +1,6 @@ The MIT License (MIT) -Copyright (c) 2014 Yuppielabel +Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors Permission is hereby granted, free of charge, to any person obtaining a copy of this software and associated documentation files (the "Software"), to deal diff --git a/README.md b/README.md index 8e9a054..7502911 100644 --- a/README.md +++ b/README.md @@ -130,7 +130,13 @@ YPDrawSignatureView is available under the MIT license. See the [LICENSE](LICENS ## Update history -### v1.0.1 - 5/2/17 +### v1.0.2 - 5/3/17 + +* Cleaning up method naming +* Delegate methods are now optional +* Sample project updated to latest settings + +#### v1.0.1 - 5/2/17 * Minor bugfix diff --git a/SignatureTest/SignatureTest.xcodeproj/project.pbxproj b/SignatureTest/SignatureTest.xcodeproj/project.pbxproj index 8305cf0..0968be8 100644 --- a/SignatureTest/SignatureTest.xcodeproj/project.pbxproj +++ b/SignatureTest/SignatureTest.xcodeproj/project.pbxproj @@ -12,9 +12,9 @@ 4BE489EE1C252F8B00741EAD /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BE489EC1C252F8B00741EAD /* Main.storyboard */; }; 4BE489F01C252F8B00741EAD /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 4BE489EF1C252F8B00741EAD /* Assets.xcassets */; }; 4BE489F31C252F8B00741EAD /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 4BE489F11C252F8B00741EAD /* LaunchScreen.storyboard */; }; - 4BE489FE1C252F8E00741EAD /* SignatureTestTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE489FD1C252F8E00741EAD /* SignatureTestTests.swift */; }; 4BE48A091C252F8F00741EAD /* SignatureTestUITests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE48A081C252F8F00741EAD /* SignatureTestUITests.swift */; }; 4BE48A171C252FC600741EAD /* YPDrawSignatureView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 4BE48A161C252FC600741EAD /* YPDrawSignatureView.swift */; }; + EACD35371EB929F000C20EF8 /* SignatureViewTest.swift in Sources */ = {isa = PBXBuildFile; fileRef = EACD35361EB929F000C20EF8 /* SignatureViewTest.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -43,12 +43,12 @@ 4BE489F21C252F8B00741EAD /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 4BE489F41C252F8C00741EAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4BE489F91C252F8E00741EAD /* SignatureTestTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignatureTestTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 4BE489FD1C252F8E00741EAD /* SignatureTestTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureTestTests.swift; sourceTree = ""; }; 4BE489FF1C252F8E00741EAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4BE48A041C252F8F00741EAD /* SignatureTestUITests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SignatureTestUITests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; 4BE48A081C252F8F00741EAD /* SignatureTestUITests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SignatureTestUITests.swift; sourceTree = ""; }; 4BE48A0A1C252F8F00741EAD /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 4BE48A161C252FC600741EAD /* YPDrawSignatureView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = YPDrawSignatureView.swift; sourceTree = ""; }; + EACD35361EB929F000C20EF8 /* SignatureViewTest.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SignatureViewTest.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -113,8 +113,8 @@ 4BE489FC1C252F8E00741EAD /* SignatureTestTests */ = { isa = PBXGroup; children = ( - 4BE489FD1C252F8E00741EAD /* SignatureTestTests.swift */, 4BE489FF1C252F8E00741EAD /* Info.plist */, + EACD35361EB929F000C20EF8 /* SignatureViewTest.swift */, ); path = SignatureTestTests; sourceTree = ""; @@ -191,7 +191,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0800; + LastUpgradeCheck = 0830; ORGANIZATIONNAME = Yuppielabel; TargetAttributes = { 4BE489E41C252F8B00741EAD = { @@ -272,7 +272,7 @@ isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; files = ( - 4BE489FE1C252F8E00741EAD /* SignatureTestTests.swift in Sources */, + EACD35371EB929F000C20EF8 /* SignatureViewTest.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -332,8 +332,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -355,7 +357,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -377,8 +379,10 @@ CLANG_WARN_DIRECT_OBJC_ISA_USAGE = YES_ERROR; CLANG_WARN_EMPTY_BODY = YES; CLANG_WARN_ENUM_CONVERSION = YES; + CLANG_WARN_INFINITE_RECURSION = YES; CLANG_WARN_INT_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_SUSPICIOUS_MOVE = YES; CLANG_WARN_UNREACHABLE_CODE = YES; CLANG_WARN__DUPLICATE_METHOD_MATCH = YES; "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; @@ -394,7 +398,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 9.2; + IPHONEOS_DEPLOYMENT_TARGET = 9.3; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; TARGETED_DEVICE_FAMILY = "1,2"; @@ -408,7 +412,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = SignatureTest/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.yuppielabel.SignatureTest; + PRODUCT_BUNDLE_IDENTIFIER = SignatureTest; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_VERSION = 3.0; }; @@ -420,7 +424,7 @@ ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = SignatureTest/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = com.yuppielabel.SignatureTest; + PRODUCT_BUNDLE_IDENTIFIER = SignatureTest; PRODUCT_NAME = "$(TARGET_NAME)"; SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; SWIFT_VERSION = 3.0; diff --git a/SignatureTest/SignatureTest/AppDelegate.swift b/SignatureTest/SignatureTest/AppDelegate.swift index ac677a1..be00bc2 100644 --- a/SignatureTest/SignatureTest/AppDelegate.swift +++ b/SignatureTest/SignatureTest/AppDelegate.swift @@ -1,11 +1,11 @@ // YPDrawSignatureView is open source -// Version 1.0 +// Version 1.0.2 // -// Copyright (c) 2014 - 2016 Yuppielabel and the project contributors +// Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors // Available under the MIT license // -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/LICENSE for license information -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/README.md for the list project contributors +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/LICENSE License Information +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/README.md Project Contributors import UIKit diff --git a/SignatureTest/SignatureTest/Info.plist b/SignatureTest/SignatureTest/Info.plist index 538c1d5..fab119f 100644 --- a/SignatureTest/SignatureTest/Info.plist +++ b/SignatureTest/SignatureTest/Info.plist @@ -2,8 +2,6 @@ - NSPhotoLibraryUsageDescription - Needs this key set for saving to PhotoRoll CFBundleDevelopmentRegion en CFBundleExecutable @@ -24,6 +22,8 @@ 1 LSRequiresIPhoneOS + NSPhotoLibraryUsageDescription + Needs this key set for saving to PhotoRoll UILaunchStoryboardName LaunchScreen UIMainStoryboardFile diff --git a/SignatureTest/SignatureTest/ViewController.swift b/SignatureTest/SignatureTest/ViewController.swift index 1f2ad43..772ff33 100644 --- a/SignatureTest/SignatureTest/ViewController.swift +++ b/SignatureTest/SignatureTest/ViewController.swift @@ -1,11 +1,11 @@ // YPDrawSignatureView is open source -// Version 0.2.2 +// Version 1.0.2 // -// Copyright (c) 2014 - 2016 Yuppielabel and the project contributors +// Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors // Available under the MIT license // -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/LICENSE for license information -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/README.md for the list project contributors +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/LICENSE License Information +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/README.md Project Contributors import UIKit @@ -18,6 +18,8 @@ class ViewController: UIViewController, YPSignatureDelegate { super.viewDidLoad() // Do any additional setup after loading the view, typically from a nib. + // Setting this view controller as the signature view delegate, so the didStart() and + // didFinish() methods below in the delegate section are called. signatureView.delegate = self } @@ -26,14 +28,17 @@ class ViewController: UIViewController, YPSignatureDelegate { // Dispose of any resources that can be recreated. } + // Function for clearing the content of signature view @IBAction func clearSignature(_ sender: UIButton) { // This is how the signature gets cleared self.signatureView.clear() } + // Function for saving signature @IBAction func saveSignature(_ sender: UIButton) { // Getting the Signature Image from self.drawSignatureView using the method getSignature(). if let signatureImage = self.signatureView.getSignature(scale: 10) { + // Saving signatureImage from the line above to the Photo Roll. // The first time you do this, the app asks for access to your pictures. UIImageWriteToSavedPhotosAlbum(signatureImage, nil, nil, nil) @@ -43,13 +48,23 @@ class ViewController: UIViewController, YPSignatureDelegate { } } - // The delegate methods gives feedback to the instanciating class - func finishedDrawing() { - print("Finished") + // MARK: - Delegate Methods + + // The delegate functions gives feedback to the instanciating class. All functions are optional, + // meaning you just implement the one you need. + + // didStart() is called right after the first touch is registered in the view. + // For example, this can be used if the view is embedded in a scroll view, temporary + // stopping it from scrolling while signing. + func didStart() { + print("Started Drawing") } - func startedDrawing() { - print("Started") + // didFinish() is called rigth after the last touch of a gesture is registered in the view. + // Can be used to enabe scrolling in a scroll view if it has previous been disabled. + func didFinish() { + print("Finished Drawing") } + } diff --git a/SignatureTest/SignatureTest/YPDrawSignatureView.swift b/SignatureTest/SignatureTest/YPDrawSignatureView.swift index 0cdf6c6..3171116 100644 --- a/SignatureTest/SignatureTest/YPDrawSignatureView.swift +++ b/SignatureTest/SignatureTest/YPDrawSignatureView.swift @@ -1,11 +1,11 @@ // YPDrawSignatureView is open source -// Version 1.0 +// Version 1.0.2 // -// Copyright (c) 2014 - 2016 Yuppielabel and the project contributors +// Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors // Available under the MIT license // -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/LICENSE for license information -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/README.md for the list project contributors +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/LICENSE License Information +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/README.md Project Contributors import UIKit @@ -24,7 +24,7 @@ import UIKit /// - getSignature() or /// - getCroppedSignature() @IBDesignable -public class YPDrawSignatureView: UIView { +final public class YPDrawSignatureView: UIView { weak var delegate: YPSignatureDelegate? @@ -59,9 +59,9 @@ public class YPDrawSignatureView: UIView { } // MARK: - Private properties - private var path = UIBezierPath() - private var points = [CGPoint](repeating: CGPoint(), count: 5) - private var controlPoint = 0 + fileprivate var path = UIBezierPath() + fileprivate var points = [CGPoint](repeating: CGPoint(), count: 5) + fileprivate var controlPoint = 0 // MARK: - Init required public init?(coder aDecoder: NSCoder) { @@ -95,6 +95,9 @@ public class YPDrawSignatureView: UIView { } if let delegate = self.delegate { + delegate.didStart() + + // Deprecated function delegate.startedDrawing() } } @@ -130,6 +133,9 @@ public class YPDrawSignatureView: UIView { } if let delegate = self.delegate { + delegate.didFinish() + + // Deprecated function delegate.finishedDrawing() } } @@ -161,7 +167,7 @@ public class YPDrawSignatureView: UIView { } - private func scale(_ rect: CGRect, byFactor factor: CGFloat) -> CGRect + fileprivate func scale(_ rect: CGRect, byFactor factor: CGFloat) -> CGRect { var scaledRect = rect scaledRect.origin.x *= factor @@ -170,14 +176,36 @@ public class YPDrawSignatureView: UIView { scaledRect.size.height *= factor return scaledRect } + + + // MARK: - Injection method for Unit Tests only + /// This method is used to inject a bezier path for testing + /// purposes only. This method is not included in the main + /// YPDrawSignatureView.swift source file by intention. + func injectBezierPath(_ path: UIBezierPath) { + self.path = path + } } -// MARK: - Protocol Methods for YPDrawSignatureViewDelegate +// MARK: - Protocol definition for YPDrawSignatureViewDelegate /// ## YPDrawSignatureViewDelegate Protocol /// YPDrawSignatureViewDelegate: -/// - startedDrawing() -/// - finishedDrawing() +/// - optional didStart() +/// - optional didFinish() protocol YPSignatureDelegate: class { - func startedDrawing() - func finishedDrawing() + func didStart() + func didFinish() + @available(iOS, deprecated: 9.3, obsoleted: 10.0, message: "Use didStart() instead") + func startedDrawing() // This method will be deprecated in a future release and should be avoided.  Instead, use didStart(). + @available(iOS, deprecated: 9.3, obsoleted: 10.0, message: "Use didFinish() instead") + func finishedDrawing() // This method will be deprecated in a future release and should be avoided.  Instead, use didFinish(). +} + +extension YPSignatureDelegate { + func didStart() {} + func didFinish() {} + + // Deprecated functions + func startedDrawing() {} + func finishedDrawing() {} } diff --git a/SignatureTest/SignatureTestTests/SignatureTestTests.swift b/SignatureTest/SignatureTestTests/SignatureTestTests.swift deleted file mode 100644 index a30d91b..0000000 --- a/SignatureTest/SignatureTestTests/SignatureTestTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// SignatureTestTests.swift -// SignatureTestTests -// -// Created by Geert-Jan Korsbø Nilsen on 19/12/15. -// Copyright © 2015 Yuppielabel. All rights reserved. -// - -import XCTest -@testable import SignatureTest - -class SignatureTestTests: XCTestCase { - - override func setUp() { - super.setUp() - // Put setup code here. This method is called before the invocation of each test method in the class. - } - - override func tearDown() { - // Put teardown code here. This method is called after the invocation of each test method in the class. - super.tearDown() - } - - func testExample() { - // This is an example of a functional test case. - // Use XCTAssert and related functions to verify your tests produce the correct results. - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure { - // Put the code you want to measure the time of here. - } - } - -} diff --git a/SignatureTest/SignatureTestTests/SignatureViewTest.swift b/SignatureTest/SignatureTestTests/SignatureViewTest.swift new file mode 100644 index 0000000..6a068f8 --- /dev/null +++ b/SignatureTest/SignatureTestTests/SignatureViewTest.swift @@ -0,0 +1,104 @@ +// YPDrawSignatureView is open source +// Version 1.0.2 +// +// Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors +// Available under the MIT license +// +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/LICENSE License Information +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/README.md Project Contributors + +import XCTest +@testable import SignatureTest + +class SignatureViewTest: XCTestCase { + + var signatureView: YPDrawSignatureView! + + override func setUp() { + super.setUp() + + signatureView = YPDrawSignatureView(frame: CGRect(x: 0, y: 0, width: 10, height: 10)) + } + + func testFrame() { + let frame = CGRect(x: 0, y: 0, width: 10, height: 10) + XCTAssertEqual(signatureView.frame, frame) + } + + func testClearSignature() { + signatureView.clear() + signatureView.strokeColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + signatureView.injectBezierPath(doodle()) + signatureView.draw(signatureView.frame) + signatureView.clear() + XCTAssertEqual(UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 0.0), getPixelColor(view2Image(signatureView), at: CGPoint(x: 4, y: 4))) + } + + func testDrawSignature() { + signatureView.clear() + signatureView.strokeColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + signatureView.injectBezierPath(doodle()) + signatureView.draw(signatureView.frame) + XCTAssertNotEqual(signatureView.signatureBackgroundColor, getPixelColor(view2Image(signatureView), at: CGPoint(x: 4, y: 4))) + } + + func testGetSignature() { + signatureView.clear() + signatureView.strokeColor = UIColor(red: 0.0, green: 0.0, blue: 0.0, alpha: 1.0) + signatureView.injectBezierPath(doodle()) + signatureView.draw(signatureView.frame) + + let signature = signatureView.getSignature() + XCTAssertNotEqual(signatureView.signatureBackgroundColor, getPixelColor(signature!, at: CGPoint(x: 4, y: 4))) + } + + +} + +// Helper Methods +extension SignatureViewTest { + + // Sample signature + func doodle() -> UIBezierPath { + + let bezierPath = UIBezierPath() + bezierPath.move(to: CGPoint(x: 4, y: 4)) + bezierPath.addCurve(to: CGPoint(x: 4.1, y: 4.1), controlPoint1: CGPoint(x: 7.57, y: 3.33), controlPoint2: CGPoint(x: 1.12, y: 3.43)) + bezierPath.addCurve(to: CGPoint(x: 4, y: 4.1), controlPoint1: CGPoint(x: 7.08, y: 4.77), controlPoint2: CGPoint(x: 11.14, y: 0.05)) + bezierPath.addCurve(to: CGPoint(x: 4, y: 5), controlPoint1: CGPoint(x: -3.14, y: 8.15), controlPoint2: CGPoint(x: 4, y: 5)) + bezierPath.addCurve(to: CGPoint(x: 4.1, y: 4), controlPoint1: CGPoint(x: 4, y: 5), controlPoint2: CGPoint(x: 1.72, y: 3.33)) + bezierPath.addCurve(to: CGPoint(x: 4.2, y: 4.2), controlPoint1: CGPoint(x: 6.48, y: 4.67), controlPoint2: CGPoint(x: -3.54, y: 7.57)) + bezierPath.addCurve(to: CGPoint(x: 4, y: 4.2), controlPoint1: CGPoint(x: 11.94, y: 0.83), controlPoint2: CGPoint(x: 4, y: 11.62)) + bezierPath.addCurve(to: CGPoint(x: 4.2, y: 4), controlPoint1: CGPoint(x: 4, y: -3.22), controlPoint2: CGPoint(x: 7.18, y: 4)) + bezierPath.addCurve(to: CGPoint(x: 4.2, y: 4.2), controlPoint1: CGPoint(x: 1.22, y: 4), controlPoint2: CGPoint(x: 4.2, y: 4.2)) + return bezierPath + } + + // Creates an UIImage of a provided view + func view2Image(_ view: UIView) -> UIImage { + + UIGraphicsBeginImageContext(view.frame.size) + view.layer.render(in: UIGraphicsGetCurrentContext()!) + let image = UIGraphicsGetImageFromCurrentImageContext() + UIGraphicsEndImageContext() + + return image! + } + + // Gets the color at a specific location in a provided view + func getPixelColor(_ image: UIImage, at pos: CGPoint) -> UIColor { + + let pixelData = image.cgImage!.dataProvider!.data + let data: UnsafePointer = CFDataGetBytePtr(pixelData) + let pixelInfo: Int = ((Int(image.size.width) * Int(pos.y)) + Int(pos.x)) * 4 + + let r = CGFloat(data[pixelInfo]) / CGFloat(255.0) + let g = CGFloat(data[pixelInfo+1]) / CGFloat(255.0) + let b = CGFloat(data[pixelInfo+2]) / CGFloat(255.0) + let a = CGFloat(data[pixelInfo+3]) / CGFloat(255.0) + + return UIColor(red: r, green: g, blue: b, alpha: a) + } +} + + diff --git a/Sources/YPDrawSignatureView.swift b/Sources/YPDrawSignatureView.swift index 0cdf6c6..ef51869 100644 --- a/Sources/YPDrawSignatureView.swift +++ b/Sources/YPDrawSignatureView.swift @@ -1,11 +1,11 @@ // YPDrawSignatureView is open source -// Version 1.0 +// Version 1.0.2 // -// Copyright (c) 2014 - 2016 Yuppielabel and the project contributors +// Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors // Available under the MIT license // -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/LICENSE for license information -// See https://github.com/yuppielabel/YPDrawSignatureView/blob/master/README.md for the list project contributors +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/LICENSE License Information +// https://github.com/GJNilsen/YPDrawSignatureView/blob/master/README.md Project Contributors import UIKit @@ -24,7 +24,7 @@ import UIKit /// - getSignature() or /// - getCroppedSignature() @IBDesignable -public class YPDrawSignatureView: UIView { +final public class YPDrawSignatureView: UIView { weak var delegate: YPSignatureDelegate? @@ -59,9 +59,9 @@ public class YPDrawSignatureView: UIView { } // MARK: - Private properties - private var path = UIBezierPath() - private var points = [CGPoint](repeating: CGPoint(), count: 5) - private var controlPoint = 0 + fileprivate var path = UIBezierPath() + fileprivate var points = [CGPoint](repeating: CGPoint(), count: 5) + fileprivate var controlPoint = 0 // MARK: - Init required public init?(coder aDecoder: NSCoder) { @@ -95,6 +95,9 @@ public class YPDrawSignatureView: UIView { } if let delegate = self.delegate { + delegate.didStart() + + // Deprecated function delegate.startedDrawing() } } @@ -130,6 +133,9 @@ public class YPDrawSignatureView: UIView { } if let delegate = self.delegate { + delegate.didFinish() + + // Deprecated function delegate.finishedDrawing() } } @@ -161,7 +167,7 @@ public class YPDrawSignatureView: UIView { } - private func scale(_ rect: CGRect, byFactor factor: CGFloat) -> CGRect + fileprivate func scale(_ rect: CGRect, byFactor factor: CGFloat) -> CGRect { var scaledRect = rect scaledRect.origin.x *= factor @@ -170,14 +176,28 @@ public class YPDrawSignatureView: UIView { scaledRect.size.height *= factor return scaledRect } + } -// MARK: - Protocol Methods for YPDrawSignatureViewDelegate +// MARK: - Protocol definition for YPDrawSignatureViewDelegate /// ## YPDrawSignatureViewDelegate Protocol /// YPDrawSignatureViewDelegate: -/// - startedDrawing() -/// - finishedDrawing() +/// - optional didStart() +/// - optional didFinish() protocol YPSignatureDelegate: class { - func startedDrawing() - func finishedDrawing() + func didStart() + func didFinish() + @available(iOS, deprecated: 9.3, obsoleted: 10.0, message: "Use didStart() instead") + func startedDrawing() // This method will be deprecated in a future release and should be avoided.  Instead, use didStart(). + @available(iOS, deprecated: 9.3, obsoleted: 10.0, message: "Use didFinish() instead") + func finishedDrawing() // This method will be deprecated in a future release and should be avoided.  Instead, use didFinish(). +} + +extension YPSignatureDelegate { + func didStart() {} + func didFinish() {} + + // Deprecated functions + func startedDrawing() {} + func finishedDrawing() {} } From 19ac3259e3981948ce00ed51608a60abc008e2cc Mon Sep 17 00:00:00 2001 From: GJ Nilsen Date: Wed, 3 May 2017 09:13:37 +0200 Subject: [PATCH 2/3] Updated documentation --- README.md | 20 +++++++++++--------- 1 file changed, 11 insertions(+), 9 deletions(-) diff --git a/README.md b/README.md index 7502911..453f20e 100644 --- a/README.md +++ b/README.md @@ -16,7 +16,7 @@ Add a new `UIView` where you want the signature capture field. Set its class to ![ScreenShot](ibss.png?raw=true "Interface Builder Attributes Inspector panel") -With the view selected, choose the IB Attributes Inspector panel to set custom values, or set them in code where you initialize the signature view. +With the view selected, choose the IB Attributes Inspector panel to set custom values, or set them in code where you initialise the signature view. #### Methods @@ -52,11 +52,13 @@ Sets the background UIColor of the view #### Optional Protocol Methods -* `startedDrawing()` +* `startedDrawing()` // Deprecated +* `didStart()` Notifies the delegate when someone starts a stroke in the view -* `finishedDrawing()` +* `finishedDrawing()` // Deprecated +* `didFinish()` Notifies the delegate when someone finishes a stroke in the view @@ -71,8 +73,8 @@ class MyViewController: UIViewController, YPSignatureDelegate { override func viewDidLoad() { super.viewDidLoad() - // Do any additional setup after loading the view, typically from a nib. - + + // Set self to YPDrawSignature View delegate drawSignatureView.delegate = self } @@ -91,12 +93,12 @@ class MyViewController: UIViewController, YPSignatureDelegate { } // MARK: - Optional delegate methods - func startedDrawing() { - // Do something when start drawing + func didStart() { + // Do something when start drawing, like disable scrolling if view is embedded in an UIScrollView or UITableViewCell } - func finishedDrawing() { - // Do something else when finished drawing + func didFinish() { + // Do something else when finished drawing, like enabling scrolling if YPDrawSignatureView is embedded in an UIScrollView or UITableViewCell } } ``` From a415faed9ab2b21b15329c845312af6f1823c456 Mon Sep 17 00:00:00 2001 From: GJ Nilsen Date: Wed, 3 May 2017 14:34:19 +0200 Subject: [PATCH 3/3] Added support for Vector Graphics Deprecated some functions and properties --- README.md | 92 +++++++++++------- .../SignatureTest.xcodeproj/project.pbxproj | 5 + SignatureTest/SignatureTest/AppDelegate.swift | 2 +- .../AppIcon.appiconset/Contents.json | 25 +++++ .../SignatureTest/Base.lproj/Main.storyboard | 16 ++- SignatureTest/SignatureTest/Info.plist | 2 +- .../SignatureTest/ViewController.swift | 4 +- .../SignatureTest/YPDrawSignatureView.swift | 51 ++++++---- Sources/YPDrawSignatureView.swift | 51 ++++++---- ibss.png | Bin 22044 -> 31874 bytes 10 files changed, 172 insertions(+), 76 deletions(-) diff --git a/README.md b/README.md index 453f20e..9271c8f 100644 --- a/README.md +++ b/README.md @@ -2,6 +2,7 @@ Simple class for capturing signatures. + ## Swift 3 The class supports Swift 3. @@ -10,6 +11,7 @@ This branch is not backwards compatible, please download the previous release if - Swift 3.0 will be supported - Swift 2.3 will not be supported + ## Usage Add a new `UIView` where you want the signature capture field. Set its class to `YPDrawSignatureView`, and connect it to an `@IBOutlet` property in your `UIViewController`. For saving and clearing the signature, add two buttons to your view controller. Hook each button up to an `@IBAction` function. @@ -18,19 +20,28 @@ Add a new `UIView` where you want the signature capture field. Set its class to With the view selected, choose the IB Attributes Inspector panel to set custom values, or set them in code where you initialise the signature view. + +## New Feature + +On ground of popular demand, added signature export as Vector Path in PDF Data Format. + + #### Methods * `clear()` -This clears the view +Clears signature * `getSignature()` -This returns the signature with the bounds of the view +Returns signature with bounds of YPDrawSignatureView instance * `getCroppedSignature()` -This returns the signature with the bounds of the signature +Returns signature with bounds of signature + +* ̀getPDFSignature()` +Returns signature as Vector Path PDF Data Format #### Properties @@ -46,18 +57,13 @@ Sets the width of the signature stroke Sets the UIColor of the signature stroke -* `signatureBackgroundColor: UIColor` - -Sets the background UIColor of the view #### Optional Protocol Methods -* `startedDrawing()` // Deprecated * `didStart()` Notifies the delegate when someone starts a stroke in the view -* `finishedDrawing()` // Deprecated * `didFinish()` Notifies the delegate when someone finishes a stroke in the view @@ -67,38 +73,56 @@ Notifies the delegate when someone finishes a stroke in the view The following sample code checks if there is a signature in the view before getting it. ``` -class MyViewController: UIViewController, YPSignatureDelegate { - - @IBOutlet weak var drawSignatureView: YPDrawSignatureView! - +class ViewController: UIViewController, YPSignatureDelegate { + + // Connect this Outlet to the Signature View + @IBOutlet weak var signatureView: YPDrawSignatureView! + override func viewDidLoad() { super.viewDidLoad() - - // Set self to YPDrawSignature View delegate - drawSignatureView.delegate = self + // Do any additional setup after loading the view, typically from a nib. + + // Setting this view controller as the signature view delegate, so the didStart() and + // didFinish() methods below in the delegate section are called. + signatureView.delegate = self } - - @IBAction func save(sender: AnyObject) { - // Checking if the view actually contains a signature - if drawSignatureView.doesContainSignature { - let img = drawSignatureView.getCroppedSignature() - // Do something with img - } else { - // Alert the user or do something else - } + + // Function for clearing the content of signature view + @IBAction func clearSignature(_ sender: UIButton) { + // This is how the signature gets cleared + self.signatureView.clear() } - - @IBAction func clear(sender: AnyObject) { - drawSignatureView.clear() + + // Function for saving signature + @IBAction func saveSignature(_ sender: UIButton) { + // Getting the Signature Image from self.drawSignatureView using the method getSignature(). + if let signatureImage = self.signatureView.getSignature(scale: 10) { + + // Saving signatureImage from the line above to the Photo Roll. + // The first time you do this, the app asks for access to your pictures. + UIImageWriteToSavedPhotosAlbum(signatureImage, nil, nil, nil) + + // Since the Signature is now saved to the Photo Roll, the View can be cleared anyway. + self.signatureView.clear() + } } - - // MARK: - Optional delegate methods + + // MARK: - Delegate Methods + + // The delegate functions gives feedback to the instanciating class. All functions are optional, + // meaning you just implement the one you need. + + // didStart() is called right after the first touch is registered in the view. + // For example, this can be used if the view is embedded in a scroll view, temporary + // stopping it from scrolling while signing. func didStart() { - // Do something when start drawing, like disable scrolling if view is embedded in an UIScrollView or UITableViewCell + print("Started Drawing") } - + + // didFinish() is called rigth after the last touch of a gesture is registered in the view. + // Can be used to enabe scrolling in a scroll view if it has previous been disabled. func didFinish() { - // Do something else when finished drawing, like enabling scrolling if YPDrawSignatureView is embedded in an UIScrollView or UITableViewCell + print("Finished Drawing") } } ``` @@ -132,8 +156,10 @@ YPDrawSignatureView is available under the MIT license. See the [LICENSE](LICENS ## Update history -### v1.0.2 - 5/3/17 +### v1.1 - 5/3/17 +* Added PDF support for exporting signature as high resolution vector graphics +* Deprecated methods and properties are properly marked * Cleaning up method naming * Delegate methods are now optional * Sample project updated to latest settings diff --git a/SignatureTest/SignatureTest.xcodeproj/project.pbxproj b/SignatureTest/SignatureTest.xcodeproj/project.pbxproj index 0968be8..4df3945 100644 --- a/SignatureTest/SignatureTest.xcodeproj/project.pbxproj +++ b/SignatureTest/SignatureTest.xcodeproj/project.pbxproj @@ -200,6 +200,7 @@ }; 4BE489F81C252F8E00741EAD = { CreatedOnToolsVersion = 7.2; + DevelopmentTeam = 784F7MSSDM; LastSwiftMigration = 0800; TestTargetID = 4BE489E41C252F8B00741EAD; }; @@ -410,6 +411,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = SignatureTest/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = SignatureTest; @@ -422,6 +424,7 @@ isa = XCBuildConfiguration; buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; + DEVELOPMENT_TEAM = ""; INFOPLIST_FILE = SignatureTest/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = SignatureTest; @@ -435,6 +438,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = 784F7MSSDM; INFOPLIST_FILE = SignatureTestTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.yuppielabel.SignatureTestTests; @@ -448,6 +452,7 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; + DEVELOPMENT_TEAM = 784F7MSSDM; INFOPLIST_FILE = SignatureTestTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.yuppielabel.SignatureTestTests; diff --git a/SignatureTest/SignatureTest/AppDelegate.swift b/SignatureTest/SignatureTest/AppDelegate.swift index be00bc2..52d49f1 100644 --- a/SignatureTest/SignatureTest/AppDelegate.swift +++ b/SignatureTest/SignatureTest/AppDelegate.swift @@ -1,5 +1,5 @@ // YPDrawSignatureView is open source -// Version 1.0.2 +// Version 1.1 // // Copyright (c) 2014 - 2017 The YPDrawSignatureView Project Contributors // Available under the MIT license diff --git a/SignatureTest/SignatureTest/Assets.xcassets/AppIcon.appiconset/Contents.json b/SignatureTest/SignatureTest/Assets.xcassets/AppIcon.appiconset/Contents.json index 36d2c80..1d060ed 100644 --- a/SignatureTest/SignatureTest/Assets.xcassets/AppIcon.appiconset/Contents.json +++ b/SignatureTest/SignatureTest/Assets.xcassets/AppIcon.appiconset/Contents.json @@ -1,5 +1,15 @@ { "images" : [ + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "2x" + }, + { + "idiom" : "iphone", + "size" : "20x20", + "scale" : "3x" + }, { "idiom" : "iphone", "size" : "29x29", @@ -30,6 +40,16 @@ "size" : "60x60", "scale" : "3x" }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "1x" + }, + { + "idiom" : "ipad", + "size" : "20x20", + "scale" : "2x" + }, { "idiom" : "ipad", "size" : "29x29", @@ -59,6 +79,11 @@ "idiom" : "ipad", "size" : "76x76", "scale" : "2x" + }, + { + "idiom" : "ipad", + "size" : "83.5x83.5", + "scale" : "2x" } ], "info" : { diff --git a/SignatureTest/SignatureTest/Base.lproj/Main.storyboard b/SignatureTest/SignatureTest/Base.lproj/Main.storyboard index 9f0959c..1fed66e 100644 --- a/SignatureTest/SignatureTest/Base.lproj/Main.storyboard +++ b/SignatureTest/SignatureTest/Base.lproj/Main.storyboard @@ -1,8 +1,11 @@ - - + + + + + - + @@ -15,12 +18,14 @@ - + + + @@ -28,14 +33,17 @@ +