From 699ce16bdb0fe3023c8651b66b2525dae6f0b158 Mon Sep 17 00:00:00 2001 From: Ramon Gilabert Date: Tue, 11 Oct 2016 13:04:02 +0200 Subject: [PATCH] Updates Ripple for Swift 3 --- Example/Ripple/Podfile | 2 + Example/Ripple/Podfile.lock | 10 +-- Example/Ripple/Ripple/AppDelegate.swift | 2 +- Example/Ripple/Ripple/ViewController.swift | 6 +- .../RippleDemo.xcodeproj/project.pbxproj | 72 +++++++++++-------- .../xcschemes/RippleDemo.xcscheme | 2 +- Ripple.xcodeproj/project.pbxproj | 32 ++++++--- .../xcshareddata/xcschemes/Ripple.xcscheme | 2 +- Sources/Ripple.swift | 57 ++++++++------- 9 files changed, 108 insertions(+), 77 deletions(-) diff --git a/Example/Ripple/Podfile b/Example/Ripple/Podfile index e7ee8ac..4d6b5cf 100644 --- a/Example/Ripple/Podfile +++ b/Example/Ripple/Podfile @@ -3,3 +3,5 @@ use_frameworks! platform :ios, '8.0' pod 'Ripple', path: '../../' + +target 'RippleDemo' diff --git a/Example/Ripple/Podfile.lock b/Example/Ripple/Podfile.lock index 013f2c8..0ec0555 100644 --- a/Example/Ripple/Podfile.lock +++ b/Example/Ripple/Podfile.lock @@ -1,14 +1,16 @@ PODS: - - Ripple (0.1.0) + - Ripple (2.1) DEPENDENCIES: - Ripple (from `../../`) EXTERNAL SOURCES: Ripple: - :path: ../../ + :path: "../../" SPEC CHECKSUMS: - Ripple: 5dba967bbe1505ae409b1a42517f19f81cfcbd3e + Ripple: fb35d2d638e9bcc03c291f14e80ae6ab1e3a3dea -COCOAPODS: 0.39.0.beta.4 +PODFILE CHECKSUM: 89640b13351516546be4227dc228ac490ac358b0 + +COCOAPODS: 1.1.0.rc.2 diff --git a/Example/Ripple/Ripple/AppDelegate.swift b/Example/Ripple/Ripple/AppDelegate.swift index ac193e7..d721adb 100644 --- a/Example/Ripple/Ripple/AppDelegate.swift +++ b/Example/Ripple/Ripple/AppDelegate.swift @@ -6,7 +6,7 @@ class AppDelegate: UIResponder, UIApplicationDelegate { lazy var rootViewController: UIViewController = ViewController() var window: UIWindow? - func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool { + func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplicationLaunchOptionsKey: Any]?) -> Bool { window = UIWindow() window?.rootViewController = rootViewController window?.makeKeyAndVisible() diff --git a/Example/Ripple/Ripple/ViewController.swift b/Example/Ripple/Ripple/ViewController.swift index d708b0f..19dab22 100644 --- a/Example/Ripple/Ripple/ViewController.swift +++ b/Example/Ripple/Ripple/ViewController.swift @@ -20,14 +20,14 @@ class ViewController: UIViewController { // MARK: - Action methods func handleTapGesture() { - let location = tapGesture.locationInView(view) + let location = tapGesture.location(in: view) ripple(location, view: view, times: 5) } // MARK: - Helper methods - override func preferredStatusBarStyle() -> UIStatusBarStyle { - return .LightContent + override var preferredStatusBarStyle : UIStatusBarStyle { + return .lightContent } } diff --git a/Example/Ripple/RippleDemo.xcodeproj/project.pbxproj b/Example/Ripple/RippleDemo.xcodeproj/project.pbxproj index bf2b0fa..b334187 100644 --- a/Example/Ripple/RippleDemo.xcodeproj/project.pbxproj +++ b/Example/Ripple/RippleDemo.xcodeproj/project.pbxproj @@ -7,24 +7,24 @@ objects = { /* Begin PBXBuildFile section */ - 070F46F3C3AE6CD551BB52C8 /* Pods.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 95915A97637700EA780F9630 /* Pods.framework */; settings = {ATTRIBUTES = (Weak, ); }; }; 292533A11CA5681E00D6C911 /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 2925339B1CA5681E00D6C911 /* AppDelegate.swift */; }; 292533A21CA5681E00D6C911 /* Assets.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 2925339C1CA5681E00D6C911 /* Assets.xcassets */; }; 292533A31CA5681E00D6C911 /* LaunchScreen.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 2925339D1CA5681E00D6C911 /* LaunchScreen.storyboard */; }; - 292533A41CA5681E00D6C911 /* Info.plist in Resources */ = {isa = PBXBuildFile; fileRef = 2925339F1CA5681E00D6C911 /* Info.plist */; }; 292533A51CA5681E00D6C911 /* ViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 292533A01CA5681E00D6C911 /* ViewController.swift */; }; + A11F573AFCC71133DAE866A5 /* Pods_RippleDemo.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 2A0384135F538EFA62641959 /* Pods_RippleDemo.framework */; }; /* End PBXBuildFile section */ /* Begin PBXFileReference section */ + 285503F76B2B12E5D15FA430 /* Pods-RippleDemo.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RippleDemo.debug.xcconfig"; path = "Pods/Target Support Files/Pods-RippleDemo/Pods-RippleDemo.debug.xcconfig"; sourceTree = ""; }; 2925339B1CA5681E00D6C911 /* AppDelegate.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AppDelegate.swift; sourceTree = ""; }; 2925339C1CA5681E00D6C911 /* Assets.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Assets.xcassets; sourceTree = ""; }; 2925339E1CA5681E00D6C911 /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/LaunchScreen.storyboard; sourceTree = ""; }; 2925339F1CA5681E00D6C911 /* Info.plist */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 292533A01CA5681E00D6C911 /* ViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = ViewController.swift; sourceTree = ""; }; - 315C769D6F352B9B6CD4923A /* Pods.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.release.xcconfig; path = "Pods/Target Support Files/Pods/Pods.release.xcconfig"; sourceTree = ""; }; + 2A0384135F538EFA62641959 /* Pods_RippleDemo.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods_RippleDemo.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 95915A97637700EA780F9630 /* Pods.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Pods.framework; sourceTree = BUILT_PRODUCTS_DIR; }; + BE62182ACEA0755F74D4546B /* Pods-RippleDemo.release.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = "Pods-RippleDemo.release.xcconfig"; path = "Pods/Target Support Files/Pods-RippleDemo/Pods-RippleDemo.release.xcconfig"; sourceTree = ""; }; D5C7F7401C3BC9CE008CDDBA /* RippleDemo.app */ = {isa = PBXFileReference; explicitFileType = wrapper.application; includeInIndex = 0; path = RippleDemo.app; sourceTree = BUILT_PRODUCTS_DIR; }; - FAE9689511B21F1FE05DC26B /* Pods.debug.xcconfig */ = {isa = PBXFileReference; includeInIndex = 1; lastKnownFileType = text.xcconfig; name = Pods.debug.xcconfig; path = "Pods/Target Support Files/Pods/Pods.debug.xcconfig"; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -32,7 +32,7 @@ isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; files = ( - 070F46F3C3AE6CD551BB52C8 /* Pods.framework in Frameworks */, + A11F573AFCC71133DAE866A5 /* Pods_RippleDemo.framework in Frameworks */, ); runOnlyForDeploymentPostprocessing = 0; }; @@ -59,22 +59,13 @@ name = "Supporting files"; sourceTree = ""; }; - 75517F88E905227B36012311 /* Pods */ = { - isa = PBXGroup; - children = ( - FAE9689511B21F1FE05DC26B /* Pods.debug.xcconfig */, - 315C769D6F352B9B6CD4923A /* Pods.release.xcconfig */, - ); - name = Pods; - sourceTree = ""; - }; D5C7F7371C3BC9CE008CDDBA = { isa = PBXGroup; children = ( 2925339A1CA5681E00D6C911 /* Ripple */, D5C7F7411C3BC9CE008CDDBA /* Products */, - 75517F88E905227B36012311 /* Pods */, D93DB8FF61C25956F41F7EC0 /* Frameworks */, + EEF6C30590301B64EE79941C /* Pods */, ); sourceTree = ""; }; @@ -90,10 +81,20 @@ isa = PBXGroup; children = ( 95915A97637700EA780F9630 /* Pods.framework */, + 2A0384135F538EFA62641959 /* Pods_RippleDemo.framework */, ); name = Frameworks; sourceTree = ""; }; + EEF6C30590301B64EE79941C /* Pods */ = { + isa = PBXGroup; + children = ( + 285503F76B2B12E5D15FA430 /* Pods-RippleDemo.debug.xcconfig */, + BE62182ACEA0755F74D4546B /* Pods-RippleDemo.release.xcconfig */, + ); + name = Pods; + sourceTree = ""; + }; /* End PBXGroup section */ /* Begin PBXNativeTarget section */ @@ -101,12 +102,12 @@ isa = PBXNativeTarget; buildConfigurationList = D5C7F7521C3BC9CE008CDDBA /* Build configuration list for PBXNativeTarget "RippleDemo" */; buildPhases = ( - 3EC637030019D26AFC22ECF1 /* Check Pods Manifest.lock */, + 570FC52FB58D696289A9C659 /* [CP] Check Pods Manifest.lock */, D5C7F73C1C3BC9CE008CDDBA /* Sources */, D5C7F73D1C3BC9CE008CDDBA /* Frameworks */, D5C7F73E1C3BC9CE008CDDBA /* Resources */, - C7BC37127BEB64213348357C /* Embed Pods Frameworks */, - 91730EB9BB8982AF27642EF6 /* Copy Pods Resources */, + 9BFFBA338A10516A68CB152E /* [CP] Embed Pods Frameworks */, + 3D05643E6A604B425CD4C9B5 /* [CP] Copy Pods Resources */, ); buildRules = ( ); @@ -124,11 +125,12 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0720; - LastUpgradeCheck = 0720; + LastUpgradeCheck = 0800; ORGANIZATIONNAME = "Hyper Interaktiv AS"; TargetAttributes = { D5C7F73F1C3BC9CE008CDDBA = { CreatedOnToolsVersion = 7.2; + LastSwiftMigration = 0800; }; }; }; @@ -157,56 +159,55 @@ files = ( 292533A21CA5681E00D6C911 /* Assets.xcassets in Resources */, 292533A31CA5681E00D6C911 /* LaunchScreen.storyboard in Resources */, - 292533A41CA5681E00D6C911 /* Info.plist in Resources */, ); runOnlyForDeploymentPostprocessing = 0; }; /* End PBXResourcesBuildPhase section */ /* Begin PBXShellScriptBuildPhase section */ - 3EC637030019D26AFC22ECF1 /* Check Pods Manifest.lock */ = { + 3D05643E6A604B425CD4C9B5 /* [CP] Copy Pods Resources */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Check Pods Manifest.lock"; + name = "[CP] Copy Pods Resources"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [[ $? != 0 ]] ; then\n cat << EOM\nerror: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\nEOM\n exit 1\nfi\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RippleDemo/Pods-RippleDemo-resources.sh\"\n"; showEnvVarsInLog = 0; }; - 91730EB9BB8982AF27642EF6 /* Copy Pods Resources */ = { + 570FC52FB58D696289A9C659 /* [CP] Check Pods Manifest.lock */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Copy Pods Resources"; + name = "[CP] Check Pods Manifest.lock"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-resources.sh\"\n"; + shellScript = "diff \"${PODS_ROOT}/../Podfile.lock\" \"${PODS_ROOT}/Manifest.lock\" > /dev/null\nif [ $? != 0 ] ; then\n # print error to STDERR\n echo \"error: The sandbox is not in sync with the Podfile.lock. Run 'pod install' or update your CocoaPods installation.\" >&2\n exit 1\nfi\n"; showEnvVarsInLog = 0; }; - C7BC37127BEB64213348357C /* Embed Pods Frameworks */ = { + 9BFFBA338A10516A68CB152E /* [CP] Embed Pods Frameworks */ = { isa = PBXShellScriptBuildPhase; buildActionMask = 2147483647; files = ( ); inputPaths = ( ); - name = "Embed Pods Frameworks"; + name = "[CP] Embed Pods Frameworks"; outputPaths = ( ); runOnlyForDeploymentPostprocessing = 0; shellPath = /bin/sh; - shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods/Pods-frameworks.sh\"\n"; + shellScript = "\"${SRCROOT}/Pods/Target Support Files/Pods-RippleDemo/Pods-RippleDemo-frameworks.sh\"\n"; showEnvVarsInLog = 0; }; /* End PBXShellScriptBuildPhase section */ @@ -248,8 +249,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"; @@ -292,8 +295,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"; @@ -312,31 +317,36 @@ IPHONEOS_DEPLOYMENT_TARGET = 9.2; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; + SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; VALIDATE_PRODUCT = YES; }; name = Release; }; D5C7F7531C3BC9CE008CDDBA /* Debug */ = { isa = XCBuildConfiguration; - baseConfigurationReference = FAE9689511B21F1FE05DC26B /* Pods.debug.xcconfig */; + baseConfigurationReference = 285503F76B2B12E5D15FA430 /* Pods-RippleDemo.debug.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Ripple/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.RamonGilabert.RippleDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Debug; }; D5C7F7541C3BC9CE008CDDBA /* Release */ = { isa = XCBuildConfiguration; - baseConfigurationReference = 315C769D6F352B9B6CD4923A /* Pods.release.xcconfig */; + baseConfigurationReference = BE62182ACEA0755F74D4546B /* Pods-RippleDemo.release.xcconfig */; buildSettings = { + ALWAYS_EMBED_SWIFT_STANDARD_LIBRARIES = YES; ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = Ripple/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = com.RamonGilabert.RippleDemo; PRODUCT_NAME = "$(TARGET_NAME)"; + SWIFT_VERSION = 3.0; }; name = Release; }; diff --git a/Example/Ripple/RippleDemo.xcodeproj/xcshareddata/xcschemes/RippleDemo.xcscheme b/Example/Ripple/RippleDemo.xcodeproj/xcshareddata/xcschemes/RippleDemo.xcscheme index 220d288..874baaf 100644 --- a/Example/Ripple/RippleDemo.xcodeproj/xcshareddata/xcschemes/RippleDemo.xcscheme +++ b/Example/Ripple/RippleDemo.xcodeproj/xcshareddata/xcschemes/RippleDemo.xcscheme @@ -1,6 +1,6 @@ 0 else { return } - dispatch_after( - dispatch_time(DISPATCH_TIME_NOW, Int64(Double(times - 1) * Double(duration) / Double(divider) * Double(NSEC_PER_SEC))), - dispatch_get_main_queue()) { - timer.invalidate() + let denominator = Double(times - 1) * Double(duration) / Double(divider) * Double(NSEC_PER_SEC) + let deadline = DispatchTime.now() + denominator + DispatchQueue.main.asyncAfter(deadline: deadline) { + timer.invalidate() } } @@ -52,10 +52,10 @@ public func ripple(center: CGPoint, view: UIView, times: Float = Float.infinity, - Returns: A ripple object, you can't do much with it though, it's just for internal use. */ -public func droplet(center: CGPoint, view: UIView, - duration: NSTimeInterval = 2, +public func droplet(_ center: CGPoint, view: UIView, + duration: TimeInterval = 2, size: CGFloat = 50, multiplier: CGFloat = 4, - color: UIColor = UIColor.whiteColor(), border: CGFloat = 2.25) -> Ripple { + color: UIColor = UIColor.white, border: CGFloat = 2.25) -> Ripple { let ripple = Ripple(center: center, view: view, duration: duration, @@ -77,16 +77,16 @@ public func calm() { timers.removeAll() } -var timers: [NSTimer] = [] +var timers: [Timer] = [] /** The ripple creator */ -public class Ripple: NSObject { +open class Ripple: NSObject { var center: CGPoint var view: UIView - var duration: NSTimeInterval + var duration: TimeInterval var size: CGSize var multiplier: CGFloat var color: UIColor @@ -94,7 +94,7 @@ public class Ripple: NSObject { var ripples: [UIView] = [] init(center: CGPoint, view: UIView, - duration: NSTimeInterval, size: CGSize, + duration: TimeInterval, size: CGSize, multiplier: CGFloat, color: UIColor, border: CGFloat) { self.center = center @@ -112,13 +112,13 @@ public class Ripple: NSObject { if let subview = view.subviews.first { view.insertSubview(ripple, aboveSubview: subview) } else { - view.insertSubview(ripple, atIndex: 0) + view.insertSubview(ripple, at: 0) } ripple.frame.origin = CGPoint(x: center.x - size.width / 2, y: center.y - size.height / 2) ripple.frame.size = size - ripple.layer.borderColor = color.CGColor + ripple.layer.borderColor = color.cgColor ripple.layer.borderWidth = border ripple.layer.cornerRadius = ripple.bounds.width / 2 @@ -127,8 +127,8 @@ public class Ripple: NSObject { animation.toValue = size.width * multiplier / 2 let boundsAnimation = CABasicAnimation(keyPath: "bounds.size") - boundsAnimation.fromValue = NSValue(CGSize: ripple.layer.bounds.size) - boundsAnimation.toValue = NSValue(CGSize: CGSize(width: size.width * multiplier, height: size.height * multiplier)) + boundsAnimation.fromValue = NSValue(cgSize: ripple.layer.bounds.size) + boundsAnimation.toValue = NSValue(cgSize: CGSize(width: size.width * multiplier, height: size.height * multiplier)) let opacityAnimation = CAKeyframeAnimation(keyPath: "opacity") opacityAnimation.values = [0, 1, 1, 1, 0] @@ -138,27 +138,30 @@ public class Ripple: NSObject { animationGroup.duration = duration animationGroup.delegate = self animationGroup.timingFunction = CAMediaTimingFunction(controlPoints: 0.22, 0.54, 0.2, 0.47) - animationGroup.removedOnCompletion = false + animationGroup.isRemovedOnCompletion = false animationGroup.fillMode = kCAFillModeForwards ripples.append(ripple) - ripple.layer.addAnimation(animationGroup, forKey: "ripple") + ripple.layer.add(animationGroup, forKey: "ripple") } + + func timerDidFire() { + activate() + } +} + +extension Ripple: CAAnimationDelegate { /** The animation delegate method that helps to do better ripples. */ - override public func animationDidStop(anim: CAAnimation, finished flag: Bool) { + open func animationDidStop(_ anim: CAAnimation, finished flag: Bool) { guard let ripple = ripples.first else { return } ripple.alpha = 0 ripple.removeFromSuperview() - ripple.layer.removeAnimationForKey("ripple") + ripple.layer.removeAnimation(forKey: "ripple") ripples.removeFirst() } - - func timerDidFire() { - activate() - } }