diff --git a/README.md b/README.md index 34f1430..debd466 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,5 @@ -## Updated for Swift 4.2 -Requires Xcode 10 and Swift 4.2. +## Updated for Swift 5 +Requires Xcode 13 and Swift 5.5 ## Installation Drop in the Spring folder to your Xcode project (make sure to enable "Copy items if needed" and "Create groups"). @@ -7,7 +7,7 @@ Drop in the Spring folder to your Xcode project (make sure to enable "Copy items Or via CocoaPods: ``` use_frameworks! -pod 'Spring', :git => 'https://github.com/MengTo/Spring.git' +pod 'Spring', :git => 'https://github.com/LexDeBash/Spring.git' ``` ## Usage with Storyboard diff --git a/Spring.podspec b/Spring.podspec index a43ed30..d1a28e6 100644 --- a/Spring.podspec +++ b/Spring.podspec @@ -1,13 +1,13 @@ Pod::Spec.new do |s| s.name = 'Spring' - s.version = '1.0.6' + s.version = '1.0.9' s.license = 'MIT' s.summary = 'A library to simplify iOS animations in Swift.' - s.homepage = 'https://github.com/MengTo/Spring' + s.homepage = 'https://github.com/LexDeBash/Spring' s.authors = { 'Meng To' => 'meng@designcode.io' } - s.source = { :git => 'https://github.com/MengTo/Spring.git', :tag => s.version.to_s } + s.source = { :git => 'https://github.com/LexDeBash/Spring.git', :tag => s.version.to_s } s.requires_arc = true - s.ios.deployment_target = '8.0' + s.ios.deployment_target = '14.0' s.tvos.deployment_target = '11.0' s.source_files = 'Spring/*.swift' s.ios.resources = ['Spring/*.xib', 'SpringApp/*.xcassets'] diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index 6c81095..c3ab5f3 100644 --- a/Spring/DesignableTabBarController.swift +++ b/Spring/DesignableTabBarController.swift @@ -47,7 +47,7 @@ import UIKit @IBInspectable var firstSelectedImage: UIImage? { didSet { if let image = firstSelectedImage { - var tabBarItems = self.tabBar.items as [UITabBarItem]? + let tabBarItems = self.tabBar.items as [UITabBarItem]? tabBarItems?[0].selectedImage = image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate) } } @@ -56,7 +56,7 @@ import UIKit @IBInspectable var secondSelectedImage: UIImage? { didSet { if let image = secondSelectedImage { - var tabBarItems = self.tabBar.items as [UITabBarItem]? + let tabBarItems = self.tabBar.items as [UITabBarItem]? tabBarItems?[1].selectedImage = image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate) } } @@ -65,7 +65,7 @@ import UIKit @IBInspectable var thirdSelectedImage: UIImage? { didSet { if let image = thirdSelectedImage { - var tabBarItems = self.tabBar.items as [UITabBarItem]? + let tabBarItems = self.tabBar.items as [UITabBarItem]? tabBarItems?[2].selectedImage = image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate) } } @@ -74,7 +74,7 @@ import UIKit @IBInspectable var fourthSelectedImage: UIImage? { didSet { if let image = fourthSelectedImage { - var tabBarItems = self.tabBar.items as [UITabBarItem]? + let tabBarItems = self.tabBar.items as [UITabBarItem]? tabBarItems?[3].selectedImage = image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate) } } @@ -83,7 +83,7 @@ import UIKit @IBInspectable var fifthSelectedImage: UIImage? { didSet { if let image = fifthSelectedImage { - var tabBarItems = self.tabBar.items as [UITabBarItem]? + let tabBarItems = self.tabBar.items as [UITabBarItem]? tabBarItems?[4].selectedImage = image.withRenderingMode(UIImage.RenderingMode.alwaysTemplate) } } diff --git a/Spring/KeyboardLayoutConstraint.swift b/Spring/KeyboardLayoutConstraint.swift index 1b45a56..f918a13 100644 --- a/Spring/KeyboardLayoutConstraint.swift +++ b/Spring/KeyboardLayoutConstraint.swift @@ -26,8 +26,8 @@ import UIKit @available(tvOS, unavailable) public class KeyboardLayoutConstraint: NSLayoutConstraint { - private var offset : CGFloat = 0 - private var keyboardVisibleHeight : CGFloat = 0 + private var offset: CGFloat = 0 + private var keyboardVisibleHeight: CGFloat = 0 @available(tvOS, unavailable) override public func awakeFromNib() { @@ -35,8 +35,18 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { offset = constant - NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)), name: UIWindow.keyboardWillShowNotification, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)), name: UIWindow.keyboardWillHideNotification, object: nil) + NotificationCenter.default.addObserver( + self, + selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification), + name: UIWindow.keyboardWillShowNotification, + object: nil + ) + NotificationCenter.default.addObserver( + self, + selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification), + name: UIWindow.keyboardWillHideNotification, + object: nil + ) } deinit { @@ -44,7 +54,6 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { } // MARK: Notification - @objc func keyboardWillShowNotification(_ notification: Notification) { if let userInfo = notification.userInfo { if let frameValue = userInfo[UIResponder.keyboardFrameEndUserInfoKey] as? NSValue { @@ -61,24 +70,19 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { UIView.animate( withDuration: TimeInterval(duration.doubleValue), delay: 0, - options: options, - animations: { - UIApplication.shared.keyWindow?.layoutIfNeeded() + options: options) { + UIApplication.shared.windows.first?.layoutIfNeeded() return - }, completion: { finished in - }) + } default: - break } - } - } @objc func keyboardWillHideNotification(_ notification: NSNotification) { keyboardVisibleHeight = 0 - self.updateConstant() + updateConstant() if let userInfo = notification.userInfo { @@ -90,12 +94,10 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { UIView.animate( withDuration: TimeInterval(duration.doubleValue), delay: 0, - options: options, - animations: { - UIApplication.shared.keyWindow?.layoutIfNeeded() + options: options) { + UIApplication.shared.windows.first?.layoutIfNeeded() return - }, completion: { finished in - }) + } default: break } @@ -103,7 +105,7 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { } func updateConstant() { - self.constant = offset + keyboardVisibleHeight + constant = offset + keyboardVisibleHeight } } diff --git a/Spring/LoadingView.swift b/Spring/LoadingView.swift index 5f62ce8..55e5e2c 100644 --- a/Spring/LoadingView.swift +++ b/Spring/LoadingView.swift @@ -50,7 +50,7 @@ public extension UIView { static let Tag = 1000 } - public func showLoading() { + func showLoading() { if self.viewWithTag(LoadingViewConstants.Tag) != nil { // If loading view is already found in current view hierachy, do nothing @@ -68,7 +68,7 @@ public extension UIView { }) } - public func hideLoading() { + func hideLoading() { if let loadingXibView = self.viewWithTag(LoadingViewConstants.Tag) { loadingXibView.alpha = 1 diff --git a/Spring/LoadingView.xib b/Spring/LoadingView.xib index 58a95a6..48a0901 100644 --- a/Spring/LoadingView.xib +++ b/Spring/LoadingView.xib @@ -1,17 +1,20 @@ - - + + + - + + + - + - + @@ -21,7 +24,7 @@ - + @@ -30,7 +33,7 @@ - + @@ -38,6 +41,7 @@ + diff --git a/Spring/Spring.swift b/Spring/Spring.swift index cf86e1a..c74c0af 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -22,7 +22,7 @@ import UIKit -@objc public protocol Springable { +public protocol Springable: AnyObject { var autostart: Bool { get set } var autohide: Bool { get set } var animation: String { get set } @@ -54,21 +54,153 @@ import UIKit public class Spring : NSObject { - private unowned var view : Springable + private unowned var view: Springable private var shouldAnimateAfterActive = false private var shouldAnimateInLayoutSubviews = true + private var autostart: Bool { + set { + view.autostart = newValue + } get { + view.autostart + } + } + private var autohide: Bool { + set { + view.autohide = newValue + } get { + view.autohide + } + } + private var animation: String { + set { + view.animation = newValue + } get { + view.animation + } + } + private var force: CGFloat { + set { + view.force = newValue + } get { + view.force + } + } + private var delay: CGFloat { + set { + view.delay = newValue + } get { + view.delay + + } + } + private var duration: CGFloat { + set { + view.duration = newValue + } get { + view.duration + } + } + private var damping: CGFloat { + set { + view.damping = newValue + } get { + view.damping + } + } + private var velocity: CGFloat { + set { + view.velocity = newValue + } get { + view.velocity + } + } + private var repeatCount: Float { + set { + view.repeatCount = newValue + } get { + view.repeatCount + } + } + private var x: CGFloat { + set { + view.x = newValue + } get { + view.x + } + } + private var y: CGFloat { + set { + view.y = newValue + } get { + view.y + } + } + private var scaleX: CGFloat { + set { + view.scaleX = newValue + } get { + view.scaleX + } + } + private var scaleY: CGFloat { + set { + view.scaleY = newValue + } get { + view.scaleY + } + } + + private var rotate: CGFloat { + set { + view.rotate = newValue + } get { + view.rotate + } + } + private var opacity: CGFloat { + set { + view.opacity = newValue + } get { + view.opacity + } + } + private var animateFrom: Bool { + set { + view.animateFrom = newValue + } get { + view.animateFrom + } + } + private var curve: String { + set { + view.curve = newValue + } get { + view.curve + } + } + + // UIView + private var layer : CALayer { return view.layer } + private var transform : CGAffineTransform { get { return view.transform } set { view.transform = newValue }} + private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } + init(_ view: Springable) { self.view = view super.init() commonInit() } - func commonInit() { - NotificationCenter.default.addObserver(self, selector: #selector(Spring.didBecomeActiveNotification(_:)), name: UIApplication.didBecomeActiveNotification, object: nil) + private func commonInit() { + NotificationCenter.default.addObserver( + self, + selector: #selector(didBecomeActiveNotification), + name: UIApplication.didBecomeActiveNotification, + object: nil + ) } - @objc func didBecomeActiveNotification(_ notification: NSNotification) { + @objc private func didBecomeActiveNotification(_ notification: NSNotification) { if shouldAnimateAfterActive { alpha = 0 animate() @@ -80,121 +212,36 @@ public class Spring : NSObject { NotificationCenter.default.removeObserver(self, name: UIApplication.didBecomeActiveNotification, object: nil) } - private var autostart: Bool { set { self.view.autostart = newValue } get { return self.view.autostart }} - private var autohide: Bool { set { self.view.autohide = newValue } get { return self.view.autohide }} - private var animation: String { set { self.view.animation = newValue } get { return self.view.animation }} - private var force: CGFloat { set { self.view.force = newValue } get { return self.view.force }} - private var delay: CGFloat { set { self.view.delay = newValue } get { return self.view.delay }} - private var duration: CGFloat { set { self.view.duration = newValue } get { return self.view.duration }} - private var damping: CGFloat { set { self.view.damping = newValue } get { return self.view.damping }} - private var velocity: CGFloat { set { self.view.velocity = newValue } get { return self.view.velocity }} - private var repeatCount: Float { set { self.view.repeatCount = newValue } get { return self.view.repeatCount }} - private var x: CGFloat { set { self.view.x = newValue } get { return self.view.x }} - private var y: CGFloat { set { self.view.y = newValue } get { return self.view.y }} - private var scaleX: CGFloat { set { self.view.scaleX = newValue } get { return self.view.scaleX }} - private var scaleY: CGFloat { set { self.view.scaleY = newValue } get { return self.view.scaleY }} - private var rotate: CGFloat { set { self.view.rotate = newValue } get { return self.view.rotate }} - private var opacity: CGFloat { set { self.view.opacity = newValue } get { return self.view.opacity }} - private var animateFrom: Bool { set { self.view.animateFrom = newValue } get { return self.view.animateFrom }} - private var curve: String { set { self.view.curve = newValue } get { return self.view.curve }} - - // UIView - private var layer : CALayer { return view.layer } - private var transform : CGAffineTransform { get { return view.transform } set { view.transform = newValue }} - private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } - - public enum AnimationPreset: String { - case SlideLeft = "slideLeft" - case SlideRight = "slideRight" - case SlideDown = "slideDown" - case SlideUp = "slideUp" - case SqueezeLeft = "squeezeLeft" - case SqueezeRight = "squeezeRight" - case SqueezeDown = "squeezeDown" - case SqueezeUp = "squeezeUp" - case FadeIn = "fadeIn" - case FadeOut = "fadeOut" - case FadeOutIn = "fadeOutIn" - case FadeInLeft = "fadeInLeft" - case FadeInRight = "fadeInRight" - case FadeInDown = "fadeInDown" - case FadeInUp = "fadeInUp" - case ZoomIn = "zoomIn" - case ZoomOut = "zoomOut" - case Fall = "fall" - case Shake = "shake" - case Pop = "pop" - case FlipX = "flipX" - case FlipY = "flipY" - case Morph = "morph" - case Squeeze = "squeeze" - case Flash = "flash" - case Wobble = "wobble" - case Swing = "swing" - } - - public enum AnimationCurve: String { - case EaseIn = "easeIn" - case EaseOut = "easeOut" - case EaseInOut = "easeInOut" - case Linear = "linear" - case Spring = "spring" - case EaseInSine = "easeInSine" - case EaseOutSine = "easeOutSine" - case EaseInOutSine = "easeInOutSine" - case EaseInQuad = "easeInQuad" - case EaseOutQuad = "easeOutQuad" - case EaseInOutQuad = "easeInOutQuad" - case EaseInCubic = "easeInCubic" - case EaseOutCubic = "easeOutCubic" - case EaseInOutCubic = "easeInOutCubic" - case EaseInQuart = "easeInQuart" - case EaseOutQuart = "easeOutQuart" - case EaseInOutQuart = "easeInOutQuart" - case EaseInQuint = "easeInQuint" - case EaseOutQuint = "easeOutQuint" - case EaseInOutQuint = "easeInOutQuint" - case EaseInExpo = "easeInExpo" - case EaseOutExpo = "easeOutExpo" - case EaseInOutExpo = "easeInOutExpo" - case EaseInCirc = "easeInCirc" - case EaseOutCirc = "easeOutCirc" - case EaseInOutCirc = "easeInOutCirc" - case EaseInBack = "easeInBack" - case EaseOutBack = "easeOutBack" - case EaseInOutBack = "easeInOutBack" - } - func animatePreset() { alpha = 0.99 if let animation = AnimationPreset(rawValue: animation) { switch animation { - case .SlideLeft: + case .slideLeft: x = 300*force - case .SlideRight: + case .slideRight: x = -300*force - case .SlideDown: + case .slideDown: y = -300*force - case .SlideUp: + case .slideUp: y = 300*force - case .SqueezeLeft: + case .squeezeLeft: x = 300 scaleX = 3*force - case .SqueezeRight: + case .squeezeRight: x = -300 scaleX = 3*force - case .SqueezeDown: + case .squeezeDown: y = -300 scaleY = 3*force - case .SqueezeUp: + case .squeezeUp: y = 300 scaleY = 3*force - case .FadeIn: + case .fadeIn: opacity = 0 - case .FadeOut: + case .fadeOut: animateFrom = false opacity = 0 - case .FadeOutIn: + case .fadeOutIn: let animation = CABasicAnimation() animation.keyPath = "opacity" animation.fromValue = 1 @@ -204,32 +251,32 @@ public class Spring : NSObject { animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) animation.autoreverses = true layer.add(animation, forKey: "fade") - case .FadeInLeft: + case .fadeInLeft: opacity = 0 x = 300*force - case .FadeInRight: + case .fadeInRight: x = -300*force opacity = 0 - case .FadeInDown: + case .fadeInDown: y = -300*force opacity = 0 - case .FadeInUp: + case .fadeInUp: y = 300*force opacity = 0 - case .ZoomIn: + case .zoomIn: opacity = 0 scaleX = 2*force scaleY = 2*force - case .ZoomOut: + case .zoomOut: animateFrom = false opacity = 0 scaleX = 2*force scaleY = 2*force - case .Fall: + case .fall: animateFrom = false rotate = 15 * CGFloat(CGFloat.pi/180) y = 600*force - case .Shake: + case .shake: let animation = CAKeyframeAnimation() animation.keyPath = "position.x" animation.values = [0, 30*force, -30*force, 30*force, 0] @@ -240,7 +287,7 @@ public class Spring : NSObject { animation.repeatCount = repeatCount animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(animation, forKey: "shake") - case .Pop: + case .pop: let animation = CAKeyframeAnimation() animation.keyPath = "transform.scale" animation.values = [0, 0.2*force, -0.2*force, 0.2*force, 0] @@ -251,7 +298,7 @@ public class Spring : NSObject { animation.repeatCount = repeatCount animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(animation, forKey: "pop") - case .FlipX: + case .flipX: rotate = 0 scaleX = 1 scaleY = 1 @@ -268,7 +315,7 @@ public class Spring : NSObject { animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) animation.timingFunction = getTimingFunction(curve: curve) layer.add(animation, forKey: "3d") - case .FlipY: + case .flipY: var perspective = CATransform3DIdentity perspective.m34 = -1.0 / layer.frame.size.width/2 @@ -283,7 +330,7 @@ public class Spring : NSObject { animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) animation.timingFunction = getTimingFunction(curve: curve) layer.add(animation, forKey: "3d") - case .Morph: + case .morph: let morphX = CAKeyframeAnimation() morphX.keyPath = "transform.scale.x" morphX.values = [1, 1.3*force, 0.7, 1.3*force, 1] @@ -303,7 +350,7 @@ public class Spring : NSObject { morphY.repeatCount = repeatCount morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(morphY, forKey: "morphY") - case .Squeeze: + case .squeeze: let morphX = CAKeyframeAnimation() morphX.keyPath = "transform.scale.x" morphX.values = [1, 1.5*force, 0.5, 1.5*force, 1] @@ -323,7 +370,7 @@ public class Spring : NSObject { morphY.repeatCount = repeatCount morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(morphY, forKey: "morphY") - case .Flash: + case .flash: let animation = CABasicAnimation() animation.keyPath = "opacity" animation.fromValue = 1 @@ -333,7 +380,7 @@ public class Spring : NSObject { animation.autoreverses = true animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(animation, forKey: "flash") - case .Wobble: + case .wobble: let animation = CAKeyframeAnimation() animation.keyPath = "transform.rotation" animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] @@ -353,7 +400,7 @@ public class Spring : NSObject { x.repeatCount = repeatCount x.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(x, forKey: "x") - case .Swing: + case .swing: let animation = CAKeyframeAnimation() animation.keyPath = "transform.rotation" animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] @@ -370,35 +417,35 @@ public class Spring : NSObject { func getTimingFunction(curve: String) -> CAMediaTimingFunction { if let curve = AnimationCurve(rawValue: curve) { switch curve { - case .EaseIn: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn) - case .EaseOut: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) - case .EaseInOut: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) - case .Linear: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) - case .Spring: return CAMediaTimingFunction(controlPoints: 0.5, 1.1+Float(force/3), 1, 1) - case .EaseInSine: return CAMediaTimingFunction(controlPoints: 0.47, 0, 0.745, 0.715) - case .EaseOutSine: return CAMediaTimingFunction(controlPoints: 0.39, 0.575, 0.565, 1) - case .EaseInOutSine: return CAMediaTimingFunction(controlPoints: 0.445, 0.05, 0.55, 0.95) - case .EaseInQuad: return CAMediaTimingFunction(controlPoints: 0.55, 0.085, 0.68, 0.53) - case .EaseOutQuad: return CAMediaTimingFunction(controlPoints: 0.25, 0.46, 0.45, 0.94) - case .EaseInOutQuad: return CAMediaTimingFunction(controlPoints: 0.455, 0.03, 0.515, 0.955) - case .EaseInCubic: return CAMediaTimingFunction(controlPoints: 0.55, 0.055, 0.675, 0.19) - case .EaseOutCubic: return CAMediaTimingFunction(controlPoints: 0.215, 0.61, 0.355, 1) - case .EaseInOutCubic: return CAMediaTimingFunction(controlPoints: 0.645, 0.045, 0.355, 1) - case .EaseInQuart: return CAMediaTimingFunction(controlPoints: 0.895, 0.03, 0.685, 0.22) - case .EaseOutQuart: return CAMediaTimingFunction(controlPoints: 0.165, 0.84, 0.44, 1) - case .EaseInOutQuart: return CAMediaTimingFunction(controlPoints: 0.77, 0, 0.175, 1) - case .EaseInQuint: return CAMediaTimingFunction(controlPoints: 0.755, 0.05, 0.855, 0.06) - case .EaseOutQuint: return CAMediaTimingFunction(controlPoints: 0.23, 1, 0.32, 1) - case .EaseInOutQuint: return CAMediaTimingFunction(controlPoints: 0.86, 0, 0.07, 1) - case .EaseInExpo: return CAMediaTimingFunction(controlPoints: 0.95, 0.05, 0.795, 0.035) - case .EaseOutExpo: return CAMediaTimingFunction(controlPoints: 0.19, 1, 0.22, 1) - case .EaseInOutExpo: return CAMediaTimingFunction(controlPoints: 1, 0, 0, 1) - case .EaseInCirc: return CAMediaTimingFunction(controlPoints: 0.6, 0.04, 0.98, 0.335) - case .EaseOutCirc: return CAMediaTimingFunction(controlPoints: 0.075, 0.82, 0.165, 1) - case .EaseInOutCirc: return CAMediaTimingFunction(controlPoints: 0.785, 0.135, 0.15, 0.86) - case .EaseInBack: return CAMediaTimingFunction(controlPoints: 0.6, -0.28, 0.735, 0.045) - case .EaseOutBack: return CAMediaTimingFunction(controlPoints: 0.175, 0.885, 0.32, 1.275) - case .EaseInOutBack: return CAMediaTimingFunction(controlPoints: 0.68, -0.55, 0.265, 1.55) + case .easeIn: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeIn) + case .easeOut: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut) + case .easeInOut: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeInEaseOut) + case .linear: return CAMediaTimingFunction(name: CAMediaTimingFunctionName.linear) + case .spring: return CAMediaTimingFunction(controlPoints: 0.5, 1.1+Float(force/3), 1, 1) + case .easeInSine: return CAMediaTimingFunction(controlPoints: 0.47, 0, 0.745, 0.715) + case .easeOutSine: return CAMediaTimingFunction(controlPoints: 0.39, 0.575, 0.565, 1) + case .easeInOutSine: return CAMediaTimingFunction(controlPoints: 0.445, 0.05, 0.55, 0.95) + case .easeInQuad: return CAMediaTimingFunction(controlPoints: 0.55, 0.085, 0.68, 0.53) + case .easeOutQuad: return CAMediaTimingFunction(controlPoints: 0.25, 0.46, 0.45, 0.94) + case .easeInOutQuad: return CAMediaTimingFunction(controlPoints: 0.455, 0.03, 0.515, 0.955) + case .easeInCubic: return CAMediaTimingFunction(controlPoints: 0.55, 0.055, 0.675, 0.19) + case .easeOutCubic: return CAMediaTimingFunction(controlPoints: 0.215, 0.61, 0.355, 1) + case .easeInOutCubic: return CAMediaTimingFunction(controlPoints: 0.645, 0.045, 0.355, 1) + case .easeInQuart: return CAMediaTimingFunction(controlPoints: 0.895, 0.03, 0.685, 0.22) + case .easeOutQuart: return CAMediaTimingFunction(controlPoints: 0.165, 0.84, 0.44, 1) + case .easeInOutQuart: return CAMediaTimingFunction(controlPoints: 0.77, 0, 0.175, 1) + case .easeInQuint: return CAMediaTimingFunction(controlPoints: 0.755, 0.05, 0.855, 0.06) + case .easeOutQuint: return CAMediaTimingFunction(controlPoints: 0.23, 1, 0.32, 1) + case .easeInOutQuint: return CAMediaTimingFunction(controlPoints: 0.86, 0, 0.07, 1) + case .easeInExpo: return CAMediaTimingFunction(controlPoints: 0.95, 0.05, 0.795, 0.035) + case .easeOutExpo: return CAMediaTimingFunction(controlPoints: 0.19, 1, 0.22, 1) + case .easeInOutExpo: return CAMediaTimingFunction(controlPoints: 1, 0, 0, 1) + case .easeInCirc: return CAMediaTimingFunction(controlPoints: 0.6, 0.04, 0.98, 0.335) + case .easeOutCirc: return CAMediaTimingFunction(controlPoints: 0.075, 0.82, 0.165, 1) + case .easeInOutCirc: return CAMediaTimingFunction(controlPoints: 0.785, 0.135, 0.15, 0.86) + case .easeInBack: return CAMediaTimingFunction(controlPoints: 0.6, -0.28, 0.735, 0.045) + case .easeOutBack: return CAMediaTimingFunction(controlPoints: 0.175, 0.885, 0.32, 1.275) + case .easeInOutBack: return CAMediaTimingFunction(controlPoints: 0.68, -0.55, 0.265, 1.55) } } return CAMediaTimingFunction(name: CAMediaTimingFunctionName.default) @@ -407,9 +454,9 @@ public class Spring : NSObject { func getAnimationOptions(curve: String) -> UIView.AnimationOptions { if let curve = AnimationCurve(rawValue: curve) { switch curve { - case .EaseIn: return UIView.AnimationOptions.curveEaseIn - case .EaseOut: return UIView.AnimationOptions.curveEaseOut - case .EaseInOut: return UIView.AnimationOptions() + case .easeIn: return UIView.AnimationOptions.curveEaseIn + case .easeOut: return UIView.AnimationOptions.curveEaseOut + case .easeInOut: return UIView.AnimationOptions() default: break } } @@ -530,3 +577,67 @@ public class Spring : NSObject { } } + +extension Spring { + public enum AnimationPreset: String, CaseIterable { + case slideLeft + case slideRight + case slideDown + case slideUp + case squeezeLeft + case squeezeRight + case squeezeDown + case squeezeUp + case fadeIn + case fadeOut + case fadeOutIn + case fadeInLeft + case fadeInRight + case fadeInDown + case fadeInUp + case zoomIn + case zoomOut + case fall + case shake + case pop + case flipX + case flipY + case morph + case squeeze + case flash + case wobble + case swing + } + + public enum AnimationCurve: String, CaseIterable { + case easeIn + case easeOut + case easeInOut + case linear + case spring + case easeInSine + case easeOutSine + case easeInOutSine + case easeInQuad + case easeOutQuad + case easeInOutQuad + case easeInCubic + case easeOutCubic + case easeInOutCubic + case easeInQuart + case easeOutQuart + case easeInOutQuart + case easeInQuint + case easeOutQuint + case easeInOutQuint + case easeInExpo + case easeOutExpo + case easeInOutExpo + case easeInCirc + case easeOutCirc + case easeInOutCirc + case easeInBack + case easeOutBack + case easeInOutBack + } +} diff --git a/Spring/UnwindSegue.swift b/Spring/UnwindSegue.swift index 53a71cb..2080094 100644 --- a/Spring/UnwindSegue.swift +++ b/Spring/UnwindSegue.swift @@ -23,5 +23,5 @@ import UIKit public extension UIViewController { - @IBAction public func unwindToViewController (_ segue: UIStoryboardSegue){} + @IBAction func unwindToViewController (_ segue: UIStoryboardSegue){} } diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index a0e8956..968738c 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -8,8 +8,6 @@ /* Begin PBXBuildFile section */ 1A4FDA381A6E44780099D309 /* Spring.h in Headers */ = {isa = PBXBuildFile; fileRef = 1A4FDA371A6E44780099D309 /* Spring.h */; settings = {ATTRIBUTES = (Public, ); }; }; - 1A4FDA3E1A6E44780099D309 /* Spring.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A4FDA331A6E44780099D309 /* Spring.framework */; }; - 1A4FDA471A6E44780099D309 /* SpringTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4FDA461A6E44780099D309 /* SpringTests.swift */; }; 1A4FDA4A1A6E44780099D309 /* Spring.framework in Frameworks */ = {isa = PBXBuildFile; fileRef = 1A4FDA331A6E44780099D309 /* Spring.framework */; }; 1A4FDA4B1A6E44780099D309 /* Spring.framework in Embed Frameworks */ = {isa = PBXBuildFile; fileRef = 1A4FDA331A6E44780099D309 /* Spring.framework */; settings = {ATTRIBUTES = (CodeSignOnCopy, RemoveHeadersOnCopy, ); }; }; 1A4FDA531A6E44A70099D309 /* LoadingView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A4FDA2A1A6E44270099D309 /* LoadingView.swift */; }; @@ -44,7 +42,6 @@ 964117461A5BE90A000E3A5A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 964117441A5BE90A000E3A5A /* Main.storyboard */; }; 964117481A5BE90A000E3A5A /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 964117471A5BE90A000E3A5A /* Images.xcassets */; }; 9641174B1A5BE90A000E3A5A /* LaunchScreen.xib in Resources */ = {isa = PBXBuildFile; fileRef = 964117491A5BE90A000E3A5A /* LaunchScreen.xib */; }; - 964117571A5BE90A000E3A5A /* SpringAppTests.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964117561A5BE90A000E3A5A /* SpringAppTests.swift */; }; 9641178B1A5BEC6F000E3A5A /* SpringViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964117881A5BEC6F000E3A5A /* SpringViewController.swift */; }; 9641178C1A5BEC6F000E3A5A /* OptionsViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964117891A5BEC6F000E3A5A /* OptionsViewController.swift */; }; 9641178D1A5BEC6F000E3A5A /* CodeViewController.swift in Sources */ = {isa = PBXBuildFile; fileRef = 9641178A1A5BEC6F000E3A5A /* CodeViewController.swift */; }; @@ -52,20 +49,6 @@ /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ - 1A4FDA3F1A6E44780099D309 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 964117331A5BE90A000E3A5A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 1A4FDA321A6E44780099D309; - remoteInfo = Spring; - }; - 1A4FDA411A6E44780099D309 /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 964117331A5BE90A000E3A5A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9641173A1A5BE90A000E3A5A; - remoteInfo = SpringApp; - }; 1A4FDA481A6E44780099D309 /* PBXContainerItemProxy */ = { isa = PBXContainerItemProxy; containerPortal = 964117331A5BE90A000E3A5A /* Project object */; @@ -73,13 +56,6 @@ remoteGlobalIDString = 1A4FDA321A6E44780099D309; remoteInfo = Spring; }; - 964117511A5BE90A000E3A5A /* PBXContainerItemProxy */ = { - isa = PBXContainerItemProxy; - containerPortal = 964117331A5BE90A000E3A5A /* Project object */; - proxyType = 1; - remoteGlobalIDString = 9641173A1A5BE90A000E3A5A; - remoteInfo = SpringApp; - }; /* End PBXContainerItemProxy section */ /* Begin PBXCopyFilesBuildPhase section */ @@ -102,9 +78,6 @@ 1A4FDA331A6E44780099D309 /* Spring.framework */ = {isa = PBXFileReference; explicitFileType = wrapper.framework; includeInIndex = 0; path = Spring.framework; sourceTree = BUILT_PRODUCTS_DIR; }; 1A4FDA361A6E44780099D309 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; 1A4FDA371A6E44780099D309 /* Spring.h */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.c.h; path = Spring.h; sourceTree = ""; }; - 1A4FDA3D1A6E44780099D309 /* SpringTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SpringTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 1A4FDA451A6E44780099D309 /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 1A4FDA461A6E44780099D309 /* SpringTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpringTests.swift; sourceTree = ""; }; 1A585F3F1A7B9530007EEB7D /* KeyboardLayoutConstraint.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = KeyboardLayoutConstraint.swift; sourceTree = ""; }; 1A9F866C1A83C5640098BE6C /* SoundPlayer.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SoundPlayer.swift; sourceTree = ""; }; 1AA7E1811AA36EFF00762D75 /* AsyncImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncImageView.swift; sourceTree = ""; }; @@ -135,9 +108,6 @@ 964117451A5BE90A000E3A5A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.storyboard; name = Base; path = Base.lproj/Main.storyboard; sourceTree = ""; }; 964117471A5BE90A000E3A5A /* Images.xcassets */ = {isa = PBXFileReference; lastKnownFileType = folder.assetcatalog; path = Images.xcassets; sourceTree = ""; }; 9641174A1A5BE90A000E3A5A /* Base */ = {isa = PBXFileReference; lastKnownFileType = file.xib; name = Base; path = Base.lproj/LaunchScreen.xib; sourceTree = ""; }; - 964117501A5BE90A000E3A5A /* SpringAppTests.xctest */ = {isa = PBXFileReference; explicitFileType = wrapper.cfbundle; includeInIndex = 0; path = SpringAppTests.xctest; sourceTree = BUILT_PRODUCTS_DIR; }; - 964117551A5BE90A000E3A5A /* Info.plist */ = {isa = PBXFileReference; lastKnownFileType = text.plist.xml; path = Info.plist; sourceTree = ""; }; - 964117561A5BE90A000E3A5A /* SpringAppTests.swift */ = {isa = PBXFileReference; lastKnownFileType = sourcecode.swift; path = SpringAppTests.swift; sourceTree = ""; }; 964117881A5BEC6F000E3A5A /* SpringViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringViewController.swift; sourceTree = ""; }; 964117891A5BEC6F000E3A5A /* OptionsViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = OptionsViewController.swift; sourceTree = ""; }; 9641178A1A5BEC6F000E3A5A /* CodeViewController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = CodeViewController.swift; sourceTree = ""; }; @@ -153,14 +123,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4FDA3A1A6E44780099D309 /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - 1A4FDA3E1A6E44780099D309 /* Spring.framework in Frameworks */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 964117381A5BE90A000E3A5A /* Frameworks */ = { isa = PBXFrameworksBuildPhase; buildActionMask = 2147483647; @@ -169,13 +131,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9641174D1A5BE90A000E3A5A /* Frameworks */ = { - isa = PBXFrameworksBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXFrameworksBuildPhase section */ /* Begin PBXGroup section */ @@ -196,23 +151,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 1A4FDA431A6E44780099D309 /* SpringTests */ = { - isa = PBXGroup; - children = ( - 1A4FDA461A6E44780099D309 /* SpringTests.swift */, - 1A4FDA441A6E44780099D309 /* Supporting Files */, - ); - path = SpringTests; - sourceTree = ""; - }; - 1A4FDA441A6E44780099D309 /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 1A4FDA451A6E44780099D309 /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; 961888D21A66BF9000295A64 /* Spring */ = { isa = PBXGroup; children = ( @@ -252,9 +190,7 @@ isa = PBXGroup; children = ( 9641173D1A5BE90A000E3A5A /* SpringApp */, - 964117531A5BE90A000E3A5A /* SpringAppTests */, 1A4FDA341A6E44780099D309 /* Spring */, - 1A4FDA431A6E44780099D309 /* SpringTests */, 9641173C1A5BE90A000E3A5A /* Products */, ); indentWidth = 4; @@ -265,9 +201,7 @@ isa = PBXGroup; children = ( 9641173B1A5BE90A000E3A5A /* SpringApp.app */, - 964117501A5BE90A000E3A5A /* SpringAppTests.xctest */, 1A4FDA331A6E44780099D309 /* Spring.framework */, - 1A4FDA3D1A6E44780099D309 /* SpringTests.xctest */, ); name = Products; sourceTree = ""; @@ -296,23 +230,6 @@ name = "Supporting Files"; sourceTree = ""; }; - 964117531A5BE90A000E3A5A /* SpringAppTests */ = { - isa = PBXGroup; - children = ( - 964117561A5BE90A000E3A5A /* SpringAppTests.swift */, - 964117541A5BE90A000E3A5A /* Supporting Files */, - ); - path = SpringAppTests; - sourceTree = ""; - }; - 964117541A5BE90A000E3A5A /* Supporting Files */ = { - isa = PBXGroup; - children = ( - 964117551A5BE90A000E3A5A /* Info.plist */, - ); - name = "Supporting Files"; - sourceTree = ""; - }; /* End PBXGroup section */ /* Begin PBXHeadersBuildPhase section */ @@ -345,25 +262,6 @@ productReference = 1A4FDA331A6E44780099D309 /* Spring.framework */; productType = "com.apple.product-type.framework"; }; - 1A4FDA3C1A6E44780099D309 /* SpringTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 1A4FDA501A6E44780099D309 /* Build configuration list for PBXNativeTarget "SpringTests" */; - buildPhases = ( - 1A4FDA391A6E44780099D309 /* Sources */, - 1A4FDA3A1A6E44780099D309 /* Frameworks */, - 1A4FDA3B1A6E44780099D309 /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 1A4FDA401A6E44780099D309 /* PBXTargetDependency */, - 1A4FDA421A6E44780099D309 /* PBXTargetDependency */, - ); - name = SpringTests; - productName = SpringTests; - productReference = 1A4FDA3D1A6E44780099D309 /* SpringTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; 9641173A1A5BE90A000E3A5A /* SpringApp */ = { isa = PBXNativeTarget; buildConfigurationList = 9641175A1A5BE90A000E3A5A /* Build configuration list for PBXNativeTarget "SpringApp" */; @@ -383,24 +281,6 @@ productReference = 9641173B1A5BE90A000E3A5A /* SpringApp.app */; productType = "com.apple.product-type.application"; }; - 9641174F1A5BE90A000E3A5A /* SpringAppTests */ = { - isa = PBXNativeTarget; - buildConfigurationList = 9641175D1A5BE90A000E3A5A /* Build configuration list for PBXNativeTarget "SpringAppTests" */; - buildPhases = ( - 9641174C1A5BE90A000E3A5A /* Sources */, - 9641174D1A5BE90A000E3A5A /* Frameworks */, - 9641174E1A5BE90A000E3A5A /* Resources */, - ); - buildRules = ( - ); - dependencies = ( - 964117521A5BE90A000E3A5A /* PBXTargetDependency */, - ); - name = SpringAppTests; - productName = SpringAppTests; - productReference = 964117501A5BE90A000E3A5A /* SpringAppTests.xctest */; - productType = "com.apple.product-type.bundle.unit-test"; - }; /* End PBXNativeTarget section */ /* Begin PBXProject section */ @@ -408,35 +288,24 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0900; + LastUpgradeCheck = 1200; ORGANIZATIONNAME = "Meng To"; TargetAttributes = { 1A4FDA321A6E44780099D309 = { CreatedOnToolsVersion = 6.1.1; LastSwiftMigration = 1020; }; - 1A4FDA3C1A6E44780099D309 = { - CreatedOnToolsVersion = 6.1.1; - LastSwiftMigration = 1020; - TestTargetID = 9641173A1A5BE90A000E3A5A; - }; 9641173A1A5BE90A000E3A5A = { CreatedOnToolsVersion = 6.2; LastSwiftMigration = 1020; }; - 9641174F1A5BE90A000E3A5A = { - CreatedOnToolsVersion = 6.2; - LastSwiftMigration = 1020; - TestTargetID = 9641173A1A5BE90A000E3A5A; - }; }; }; buildConfigurationList = 964117361A5BE90A000E3A5A /* Build configuration list for PBXProject "SpringApp" */; compatibilityVersion = "Xcode 3.2"; - developmentRegion = English; + developmentRegion = en; hasScannedForEncodings = 0; knownRegions = ( - English, en, Base, ); @@ -446,9 +315,7 @@ projectRoot = ""; targets = ( 9641173A1A5BE90A000E3A5A /* SpringApp */, - 9641174F1A5BE90A000E3A5A /* SpringAppTests */, 1A4FDA321A6E44780099D309 /* Spring */, - 1A4FDA3C1A6E44780099D309 /* SpringTests */, ); }; /* End PBXProject section */ @@ -463,13 +330,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4FDA3B1A6E44780099D309 /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; 964117391A5BE90A000E3A5A /* Resources */ = { isa = PBXResourcesBuildPhase; buildActionMask = 2147483647; @@ -480,13 +340,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9641174E1A5BE90A000E3A5A /* Resources */ = { - isa = PBXResourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXResourcesBuildPhase section */ /* Begin PBXSourcesBuildPhase section */ @@ -523,14 +376,6 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 1A4FDA391A6E44780099D309 /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 1A4FDA471A6E44780099D309 /* SpringTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; 964117371A5BE90A000E3A5A /* Sources */ = { isa = PBXSourcesBuildPhase; buildActionMask = 2147483647; @@ -543,37 +388,14 @@ ); runOnlyForDeploymentPostprocessing = 0; }; - 9641174C1A5BE90A000E3A5A /* Sources */ = { - isa = PBXSourcesBuildPhase; - buildActionMask = 2147483647; - files = ( - 964117571A5BE90A000E3A5A /* SpringAppTests.swift in Sources */, - ); - runOnlyForDeploymentPostprocessing = 0; - }; /* End PBXSourcesBuildPhase section */ /* Begin PBXTargetDependency section */ - 1A4FDA401A6E44780099D309 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 1A4FDA321A6E44780099D309 /* Spring */; - targetProxy = 1A4FDA3F1A6E44780099D309 /* PBXContainerItemProxy */; - }; - 1A4FDA421A6E44780099D309 /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9641173A1A5BE90A000E3A5A /* SpringApp */; - targetProxy = 1A4FDA411A6E44780099D309 /* PBXContainerItemProxy */; - }; 1A4FDA491A6E44780099D309 /* PBXTargetDependency */ = { isa = PBXTargetDependency; target = 1A4FDA321A6E44780099D309 /* Spring */; targetProxy = 1A4FDA481A6E44780099D309 /* PBXContainerItemProxy */; }; - 964117521A5BE90A000E3A5A /* PBXTargetDependency */ = { - isa = PBXTargetDependency; - target = 9641173A1A5BE90A000E3A5A /* SpringApp */; - targetProxy = 964117511A5BE90A000E3A5A /* PBXContainerItemProxy */; - }; /* End PBXTargetDependency section */ /* Begin PBXVariantGroup section */ @@ -611,7 +433,7 @@ ); INFOPLIST_FILE = Spring/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -634,7 +456,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Spring/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -647,41 +469,11 @@ }; name = Release; }; - 1A4FDA511A6E44780099D309 /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = SpringTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.jamztang.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; - }; - name = Debug; - }; - 1A4FDA521A6E44780099D309 /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - INFOPLIST_FILE = SpringTests/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "com.jamztang.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; - }; - name = Release; - }; 964117581A5BE90A000E3A5A /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -690,14 +482,17 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -722,7 +517,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.2; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; MTL_ENABLE_DEBUG_INFO = YES; ONLY_ACTIVE_ARCH = YES; SDKROOT = iphoneos; @@ -735,6 +530,7 @@ isa = XCBuildConfiguration; buildSettings = { ALWAYS_SEARCH_USER_PATHS = NO; + CLANG_ANALYZER_LOCALIZABILITY_NONLOCALIZED = YES; CLANG_CXX_LANGUAGE_STANDARD = "gnu++0x"; CLANG_CXX_LIBRARY = "libc++"; CLANG_ENABLE_MODULES = YES; @@ -743,14 +539,17 @@ CLANG_WARN_BOOL_CONVERSION = YES; CLANG_WARN_COMMA = YES; CLANG_WARN_CONSTANT_CONVERSION = YES; + CLANG_WARN_DEPRECATED_OBJC_IMPLEMENTATIONS = YES; 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_NON_LITERAL_NULL_CONVERSION = YES; + CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES; CLANG_WARN_OBJC_LITERAL_CONVERSION = YES; CLANG_WARN_OBJC_ROOT_CLASS = YES_ERROR; + CLANG_WARN_QUOTED_INCLUDE_IN_FRAMEWORK_HEADER = YES; CLANG_WARN_RANGE_LOOP_ANALYSIS = YES; CLANG_WARN_STRICT_PROTOTYPES = YES; CLANG_WARN_SUSPICIOUS_MOVE = YES; @@ -768,7 +567,7 @@ GCC_WARN_UNINITIALIZED_AUTOS = YES_AGGRESSIVE; GCC_WARN_UNUSED_FUNCTION = YES; GCC_WARN_UNUSED_VARIABLE = YES; - IPHONEOS_DEPLOYMENT_TARGET = 8.2; + IPHONEOS_DEPLOYMENT_TARGET = 13.1; MTL_ENABLE_DEBUG_INFO = NO; SDKROOT = iphoneos; SWIFT_SWIFT3_OBJC_INFERENCE = Off; @@ -781,7 +580,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = SpringApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -795,7 +594,7 @@ buildSettings = { ASSETCATALOG_COMPILER_APPICON_NAME = AppIcon; INFOPLIST_FILE = SpringApp/Info.plist; - IPHONEOS_DEPLOYMENT_TARGET = 8.0; + IPHONEOS_DEPLOYMENT_TARGET = 14.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; @@ -805,37 +604,6 @@ }; name = Release; }; - 9641175E1A5BE90A000E3A5A /* Debug */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - GCC_PREPROCESSOR_DEFINITIONS = ( - "DEBUG=1", - "$(inherited)", - ); - INFOPLIST_FILE = SpringAppTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; - }; - name = Debug; - }; - 9641175F1A5BE90A000E3A5A /* Release */ = { - isa = XCBuildConfiguration; - buildSettings = { - BUNDLE_LOADER = "$(TEST_HOST)"; - INFOPLIST_FILE = SpringAppTests/Info.plist; - LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; - PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; - PRODUCT_NAME = "$(TARGET_NAME)"; - SWIFT_OPTIMIZATION_LEVEL = "-Owholemodule"; - SWIFT_VERSION = 5.0; - TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; - }; - name = Release; - }; /* End XCBuildConfiguration section */ /* Begin XCConfigurationList section */ @@ -848,15 +616,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 1A4FDA501A6E44780099D309 /* Build configuration list for PBXNativeTarget "SpringTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 1A4FDA511A6E44780099D309 /* Debug */, - 1A4FDA521A6E44780099D309 /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; 964117361A5BE90A000E3A5A /* Build configuration list for PBXProject "SpringApp" */ = { isa = XCConfigurationList; buildConfigurations = ( @@ -875,15 +634,6 @@ defaultConfigurationIsVisible = 0; defaultConfigurationName = Release; }; - 9641175D1A5BE90A000E3A5A /* Build configuration list for PBXNativeTarget "SpringAppTests" */ = { - isa = XCConfigurationList; - buildConfigurations = ( - 9641175E1A5BE90A000E3A5A /* Debug */, - 9641175F1A5BE90A000E3A5A /* Release */, - ); - defaultConfigurationIsVisible = 0; - defaultConfigurationName = Release; - }; /* End XCConfigurationList section */ }; rootObject = 964117331A5BE90A000E3A5A /* Project object */; diff --git a/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme index ecfaae8..89b2628 100644 --- a/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme +++ b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme @@ -1,6 +1,6 @@ - - - - + + + + @@ -77,17 +86,6 @@ - - - - - - - - armv7 + UIStatusBarStyle + UIStatusBarStyleDefault UISupportedInterfaceOrientations UIInterfaceOrientationPortrait @@ -37,6 +39,6 @@ UIInterfaceOrientationLandscapeRight UIViewControllerBasedStatusBarAppearance - + diff --git a/SpringApp/OptionsViewController.swift b/SpringApp/OptionsViewController.swift index be62011..5ae2c28 100644 --- a/SpringApp/OptionsViewController.swift +++ b/SpringApp/OptionsViewController.swift @@ -6,10 +6,9 @@ // Copyright (c) 2015 Meng To. All rights reserved. // -import UIKit import Spring -protocol OptionsViewControllerDelegate: class { +protocol OptionsViewControllerDelegate: AnyObject { func dampingSliderChanged(_ sender: AnyObject) func velocitySliderChanged(_ sender: AnyObject) func scaleSliderChanged(_ sender: AnyObject) @@ -47,6 +46,10 @@ class OptionsViewController: UIViewController { weak var delegate: OptionsViewControllerDelegate? var data: SpringView! + override var preferredStatusBarStyle: UIStatusBarStyle { + .lightContent + } + override func viewDidLoad() { super.viewDidLoad() @@ -107,19 +110,19 @@ class OptionsViewController: UIViewController { delegate?.resetButtonPressed(sender) dismiss(animated: true, completion: nil) - UIApplication.shared.sendAction(#selector(SpringViewController.maximizeView(_:)), to: nil, from: self, for: nil) + UIApplication.shared.sendAction(#selector(SpringViewController.maximizeView), to: nil, from: self, for: nil) } @IBAction func closeButtonPressed(_ sender: AnyObject) { dismiss(animated: true, completion: nil) - UIApplication.shared.sendAction(#selector(SpringViewController.maximizeView(_:)), to: nil, from: self, for: nil) + UIApplication.shared.sendAction(#selector(SpringViewController.maximizeView), to: nil, from: self, for: nil) } override func viewDidAppear(_ animated: Bool) { super.viewDidAppear(true) - UIApplication.shared.sendAction(#selector(SpringViewController.minimizeView(_:)), to: nil, from: self, for: nil) + UIApplication.shared.sendAction(#selector(SpringViewController.minimizeView), to: nil, from: self, for: nil) modalView.animate() } diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index 6a4ea1b..78371e3 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -10,7 +10,7 @@ import UIKit import Spring class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerViewDataSource, OptionsViewControllerDelegate { - + @IBOutlet weak var delayLabel: UILabel! @IBOutlet weak var durationLabel: UILabel! @IBOutlet weak var forceLabel: UILabel! @@ -20,8 +20,8 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView @IBOutlet weak var ballView: SpringView! @IBOutlet weak var animationPicker: UIPickerView! - var selectedRow: Int = 0 - var selectedEasing: Int = 0 + var selectedRow = 0 + var selectedEasing = 0 var selectedForce: CGFloat = 1 var selectedDuration: CGFloat = 1 @@ -34,6 +34,21 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView var selectedY: CGFloat = 0 var selectedRotate: CGFloat = 0 + var isBall = false + + let animations = Spring.AnimationPreset.allCases + let animationCurves = Spring.AnimationCurve.allCases + + override func viewDidLoad() { + super.viewDidLoad() + animationPicker.delegate = self + animationPicker.dataSource = self + } + + override var preferredStatusBarStyle: UIStatusBarStyle { + .default + } + @IBAction func forceSliderChanged(_ sender: AnyObject) { selectedForce = sender.value(forKey: "value") as! CGFloat animateView() @@ -49,7 +64,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView animateView() delayLabel.text = String(format: "Delay: %.1f", Double(selectedDelay)) } - + func dampingSliderChanged(_ sender: AnyObject) { selectedDamping = sender.value(forKey: "value") as! CGFloat animateView() @@ -80,12 +95,12 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView animateView() } - func animateView() { + private func animateView() { setOptions() ballView.animate() } - func setOptions() { + private func setOptions() { ballView.force = selectedForce ballView.duration = selectedDuration ballView.delay = selectedDelay @@ -102,87 +117,16 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView ballView.curve = animationCurves[selectedEasing].rawValue } - @objc func minimizeView(_ sender: AnyObject) { - SpringAnimation.spring(duration: 0.7, animations: { + @objc func minimizeView(_ sender: AnyObject) { + SpringAnimation.spring(duration: 0.7) { self.view.transform = CGAffineTransform(scaleX: 0.935, y: 0.935) - }) - UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.lightContent, animated: true) + } } - @objc func maximizeView(_ sender: AnyObject) { - SpringAnimation.spring(duration: 0.7, animations: { + @objc func maximizeView(_ sender: AnyObject) { + SpringAnimation.spring(duration: 0.7) { self.view.transform = CGAffineTransform(scaleX: 1, y: 1) - }) - UIApplication.shared.setStatusBarStyle(UIStatusBarStyle.default, animated: true) - } - - let animations: [Spring.AnimationPreset] = [ - .Shake, - .Pop, - .Morph, - .Squeeze, - .Wobble, - .Swing, - .FlipX, - .FlipY, - .Fall, - .SqueezeLeft, - .SqueezeRight, - .SqueezeDown, - .SqueezeUp, - .SlideLeft, - .SlideRight, - .SlideDown, - .SlideUp, - .FadeIn, - .FadeOut, - .FadeInLeft, - .FadeInRight, - .FadeInDown, - .FadeInUp, - .ZoomIn, - .ZoomOut, - .Flash - ] - - var animationCurves: [Spring.AnimationCurve] = [ - .EaseIn, - .EaseOut, - .EaseInOut, - .Linear, - .Spring, - .EaseInSine, - .EaseOutSine, - .EaseInOutSine, - .EaseInQuad, - .EaseOutQuad, - .EaseInOutQuad, - .EaseInCubic, - .EaseOutCubic, - .EaseInOutCubic, - .EaseInQuart, - .EaseOutQuart, - .EaseInOutQuart, - .EaseInQuint, - .EaseOutQuint, - .EaseInOutQuint, - .EaseInExpo, - .EaseOutExpo, - .EaseInOutExpo, - .EaseInCirc, - .EaseOutCirc, - .EaseInOutCirc, - .EaseInBack, - .EaseOutBack, - .EaseInOutBack - ] - - override func viewDidLoad() { - super.viewDidLoad() - - animationPicker.delegate = self - animationPicker.dataSource = self - animationPicker.showsSelectionIndicator = true + } } @IBAction func ballButtonPressed(_ sender: AnyObject) { @@ -198,9 +142,8 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView animateView() } - var isBall = false func changeBall() { - isBall = !isBall + isBall.toggle() let animation = CABasicAnimation() let halfWidth = ballView.frame.width / 2 let cornerRadius: CGFloat = isBall ? halfWidth : 10 @@ -265,8 +208,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView optionsViewController.delegate = self setOptions() optionsViewController.data = ballView - } - else if let codeViewController = segue.destination as? CodeViewController { + } else if let codeViewController = segue.destination as? CodeViewController { setOptions() codeViewController.data = ballView } diff --git a/SpringAppTests/Info.plist b/SpringAppTests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/SpringAppTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/SpringAppTests/SpringAppTests.swift b/SpringAppTests/SpringAppTests.swift deleted file mode 100644 index ac2484b..0000000 --- a/SpringAppTests/SpringAppTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// SpringAppTests.swift -// SpringAppTests -// -// Created by Meng To on 2015-01-06. -// Copyright (c) 2015 Meng To. All rights reserved. -// - -import UIKit -import XCTest - -class SpringAppTests: 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. - XCTAssert(true, "Pass") - } - - 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/SpringTests/Info.plist b/SpringTests/Info.plist deleted file mode 100644 index ba72822..0000000 --- a/SpringTests/Info.plist +++ /dev/null @@ -1,24 +0,0 @@ - - - - - CFBundleDevelopmentRegion - en - CFBundleExecutable - $(EXECUTABLE_NAME) - CFBundleIdentifier - $(PRODUCT_BUNDLE_IDENTIFIER) - CFBundleInfoDictionaryVersion - 6.0 - CFBundleName - $(PRODUCT_NAME) - CFBundlePackageType - BNDL - CFBundleShortVersionString - 1.0 - CFBundleSignature - ???? - CFBundleVersion - 1 - - diff --git a/SpringTests/SpringTests.swift b/SpringTests/SpringTests.swift deleted file mode 100644 index 938737d..0000000 --- a/SpringTests/SpringTests.swift +++ /dev/null @@ -1,36 +0,0 @@ -// -// SpringTests.swift -// SpringTests -// -// Created by James Tang on 20/1/15. -// Copyright (c) 2015 Meng To. All rights reserved. -// - -import UIKit -import XCTest - -class SpringTests: 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. - XCTAssert(true, "Pass") - } - - func testPerformanceExample() { - // This is an example of a performance test case. - self.measure() { - // Put the code you want to measure the time of here. - } - } - -}