From bb4c8b72a9b808e2102e0efe8239b09e7f7d0208 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 1 Feb 2015 14:36:40 +0100 Subject: [PATCH 001/113] Remove ignored Xcode workspace files - They are specific to each user who clones and checks out the project. --- .../xcshareddata/SpringApp.xccheckout | 41 ------------------ .../UserInterfaceState.xcuserstate | Bin 30208 -> 0 bytes 2 files changed, 41 deletions(-) delete mode 100644 SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout delete mode 100644 SpringApp.xcodeproj/project.xcworkspace/xcuserdata/mengto.xcuserdatad/UserInterfaceState.xcuserstate diff --git a/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout b/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout deleted file mode 100644 index 272c9d7..0000000 --- a/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout +++ /dev/null @@ -1,41 +0,0 @@ - - - - - IDESourceControlProjectFavoriteDictionaryKey - - IDESourceControlProjectIdentifier - A5CDD406-2D04-44CC-8B76-9B40C5FCC0AA - IDESourceControlProjectName - SpringApp - IDESourceControlProjectOriginsDictionary - - 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E - https://github.com/MengTo/Spring.git - - IDESourceControlProjectPath - SpringApp.xcodeproj - IDESourceControlProjectRelativeInstallPathDictionary - IDESourceControlProjectVersion - 111 - IDESourceControlProjectWCConfigurations - - - IDESourceControlRepositoryExtensionIdentifierKey - public.vcs.git - IDESourceControlWCCIdentifierKey - 30465C3FE587DE41DC8D7C50D84E40C5B622D54F - IDESourceControlWCCName - - - - IDESourceControlRepositoryExtensionIdentifierKey - public.vcs.git - IDESourceControlWCCIdentifierKey - 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E - IDESourceControlWCCName - Spring - - - - diff --git a/SpringApp.xcodeproj/project.xcworkspace/xcuserdata/mengto.xcuserdatad/UserInterfaceState.xcuserstate b/SpringApp.xcodeproj/project.xcworkspace/xcuserdata/mengto.xcuserdatad/UserInterfaceState.xcuserstate deleted file mode 100644 index 7b64b7044b18ec988959336f47639adfebaefc82..0000000000000000000000000000000000000000 GIT binary patch literal 0 HcmV?d00001 literal 30208 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 EA344uX8-^I From 7bae966d6471b8afe12e3bb12ab1a8d3f7ffaf0f Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 1 Feb 2015 14:36:57 +0100 Subject: [PATCH 002/113] Remove ignored Xcode files - They are specific to each user who clones and checks out the project. --- .../xcdebugger/Breakpoints_v2.xcbkptlist | 5 - .../xcschemes/SpringApp.xcscheme | 136 ------------------ .../xcschemes/xcschememanagement.plist | 37 ----- 3 files changed, 178 deletions(-) delete mode 100644 SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist delete mode 100644 SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/SpringApp.xcscheme delete mode 100644 SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/xcschememanagement.plist diff --git a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist b/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist deleted file mode 100644 index fe2b454..0000000 --- a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcdebugger/Breakpoints_v2.xcbkptlist +++ /dev/null @@ -1,5 +0,0 @@ - - - diff --git a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/SpringApp.xcscheme b/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/SpringApp.xcscheme deleted file mode 100644 index 9ea424c..0000000 --- a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/SpringApp.xcscheme +++ /dev/null @@ -1,136 +0,0 @@ - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - - diff --git a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/xcschememanagement.plist b/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/xcschememanagement.plist deleted file mode 100644 index 48ba9d1..0000000 --- a/SpringApp.xcodeproj/xcuserdata/mengto.xcuserdatad/xcschemes/xcschememanagement.plist +++ /dev/null @@ -1,37 +0,0 @@ - - - - - SchemeUserState - - SpringApp.xcscheme - - orderHint - 0 - - - SuppressBuildableAutocreation - - 1A4FDA321A6E44780099D309 - - primary - - - 1A4FDA3C1A6E44780099D309 - - primary - - - 9641173A1A5BE90A000E3A5A - - primary - - - 9641174F1A5BE90A000E3A5A - - primary - - - - - From e848d3cd6aaf13ba14f4394b9bd0c977718af50a Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 1 Feb 2015 14:37:35 +0100 Subject: [PATCH 003/113] Add a shared Xcode scheme for the Spring framework --- .../xcshareddata/xcschemes/Spring.xcscheme | 77 +++++++++++++++++++ 1 file changed, 77 insertions(+) create mode 100644 SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme diff --git a/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme new file mode 100644 index 0000000..492fc4d --- /dev/null +++ b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme @@ -0,0 +1,77 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From f32a485a71671ece8ef23bc6d9c7b6c391fd5e21 Mon Sep 17 00:00:00 2001 From: Aron Cedercrantz Date: Sun, 1 Feb 2015 14:38:39 +0100 Subject: [PATCH 004/113] Change Spring framework deployment target to 8.0 - The SpringApp target already had this iOS 8.0 as its target. This changes makes both of the use the same. --- SpringApp.xcodeproj/project.pbxproj | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index d156ef2..f808f6f 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -586,7 +586,7 @@ ); INFOPLIST_FILE = Spring/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; @@ -606,7 +606,7 @@ DYLIB_INSTALL_NAME_BASE = "@rpath"; INFOPLIST_FILE = Spring/Info.plist; INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; - IPHONEOS_DEPLOYMENT_TARGET = 8.1; + IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; From b5519651c4cd63b38ca65c60efeefd24a870393c Mon Sep 17 00:00:00 2001 From: Camilo Vera Date: Mon, 2 Feb 2015 15:07:39 -0800 Subject: [PATCH 005/113] prevents retain cycle --- Spring/Spring.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 32926bb..348e103 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -48,7 +48,7 @@ import UIKit public class Spring : NSObject { - private var view : Springable + private unowned var view : Springable init(_ view: Springable) { self.view = view From f2af1132f2d819628611328efef74a06b1a3fecb Mon Sep 17 00:00:00 2001 From: Camo Date: Tue, 3 Feb 2015 00:30:06 -0800 Subject: [PATCH 006/113] Weakifying (is this even a word?) spring for UIView.animate...., since the completion might be called when the spring is already nil --- Spring/Spring.swift | 39 +++++++++++++++++++++------------------ 1 file changed, 21 insertions(+), 18 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 348e103..6f1da6f 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -372,26 +372,29 @@ public class Spring : NSObject { usingSpringWithDamping: damping, initialSpringVelocity: velocity, options: getAnimationOptions(curve), - animations: { - - if self.animateFrom { - self.transform = CGAffineTransformIdentity - self.alpha = 1 - } - else { - let translate = CGAffineTransformMakeTranslation(self.x, self.y) - let scale = CGAffineTransformMakeScale(self.scaleX, self.scaleY) - let rotate = CGAffineTransformMakeRotation(self.rotate) - let translateAndScale = CGAffineTransformConcat(translate, scale) - self.transform = CGAffineTransformConcat(rotate, translateAndScale) - - self.alpha = self.opacity + animations: { [weak self] in + if let _self = self + { + if _self.animateFrom { + _self.transform = CGAffineTransformIdentity + _self.alpha = 1 + } + else { + let translate = CGAffineTransformMakeTranslation(_self.x, _self.y) + let scale = CGAffineTransformMakeScale(_self.scaleX, _self.scaleY) + let rotate = CGAffineTransformMakeRotation(_self.rotate) + let translateAndScale = CGAffineTransformConcat(translate, scale) + _self.transform = CGAffineTransformConcat(rotate, translateAndScale) + + _self.alpha = _self.opacity + } + } - - }, { finished in - + + }, { [weak self] finished in + completion() - self.resetAll() + self?.resetAll() }) } From e292137b3946decb49f4ec3e8fb0e907d2a02ce0 Mon Sep 17 00:00:00 2001 From: James Tang Date: Wed, 4 Feb 2015 19:06:48 +0800 Subject: [PATCH 007/113] Add URL helper --- Spring/Misc.swift | 4 ++++ 1 file changed, 4 insertions(+) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 2e2f1ae..bf17af0 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -24,6 +24,10 @@ import UIKit public extension String { public var length: Int { return countElements(self) } + + public func toURL() -> NSURL? { + return NSURL(string: self) + } } public func htmlToAttributedString(text: String) -> NSAttributedString! { From c25bcdaa34e00daf61c663c9b896ad44c8703213 Mon Sep 17 00:00:00 2001 From: James Tang Date: Wed, 4 Feb 2015 20:10:51 +0800 Subject: [PATCH 008/113] NSDateFormatter is expensive to create --- Spring/Misc.swift | 22 ++++++++++++++++------ 1 file changed, 16 insertions(+), 6 deletions(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index bf17af0..0fdb931 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -115,16 +115,26 @@ public func UIColorFromRGB(rgbValue: UInt) -> UIColor { ) } +var dateFormatter : NSDateFormatter? + public func stringFromDate(date: NSDate, format: String) -> String { - var dateFormatter = NSDateFormatter() - dateFormatter.dateFormat = format - return dateFormatter.stringFromDate(date) + + if dateFormatter == nil { + dateFormatter = NSDateFormatter() + } + + dateFormatter!.dateFormat = format + return dateFormatter!.stringFromDate(date) } public func dateFromString(date: String, format: String) -> NSDate { - var dateFormatter = NSDateFormatter() - dateFormatter.dateFormat = format - return dateFormatter.dateFromString(date)! + + if dateFormatter == nil { + dateFormatter = NSDateFormatter() + } + + dateFormatter!.dateFormat = format + return dateFormatter!.dateFromString(date)! } public func randomStringWithLength (len : Int) -> NSString { From e94023104a314b6e6ec35c58a406cbe7722cd532 Mon Sep 17 00:00:00 2001 From: Meng To Date: Thu, 5 Feb 2015 00:20:21 +0800 Subject: [PATCH 009/113] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 974d766..401589e 100644 --- a/README.md +++ b/README.md @@ -31,7 +31,7 @@ In Identity Inspector, connect the UIView to SpringView Class and set the animat animateTo() animateToNext { ... } -## Presets +## Animation shake pop morph From 648198a4e13bfa06411e98e9c8f37cde40b3e103 Mon Sep 17 00:00:00 2001 From: James Tang Date: Thu, 5 Feb 2015 23:39:40 +0800 Subject: [PATCH 010/113] Add SoundPlayer --- Spring/SoundPlayer.swift | 62 +++++++++++++++++++++++++++++ SpringApp.xcodeproj/project.pbxproj | 4 ++ 2 files changed, 66 insertions(+) create mode 100644 Spring/SoundPlayer.swift diff --git a/Spring/SoundPlayer.swift b/Spring/SoundPlayer.swift new file mode 100644 index 0000000..d39830c --- /dev/null +++ b/Spring/SoundPlayer.swift @@ -0,0 +1,62 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 James Tang (j@jamztang.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import UIKit +import AudioToolbox + +public class SoundPlayer: NSObject { + + @IBInspectable var filename : String? + @IBInspectable var enabled : Bool = true + + private struct Internal { + static var cache = [NSURL:SystemSoundID]() + } + + public func playSound(soundFile:String) { + + if !enabled { + return + } + + if let url = NSBundle.mainBundle().URLForResource(soundFile, withExtension: nil) { + + var soundID : SystemSoundID = Internal.cache[url] ?? 0 + + if soundID == 0 { + AudioServicesCreateSystemSoundID(url, &soundID) + Internal.cache[url] = soundID + } + + AudioServicesPlaySystemSound(soundID) + + } else { + println("Could not find sound file name `\(soundFile)`") + } + } + + @IBAction public func play(sender: AnyObject?) { + if let filename = filename { + self.playSound(filename) + } + } +} diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index d156ef2..52558d0 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -36,6 +36,7 @@ 1A4FDA6A1A6E44A70099D309 /* TransitionZoom.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961888E41A66BF9000295A64 /* TransitionZoom.swift */; }; 1A4FDA6B1A6E44A70099D309 /* UnwindSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961888E51A66BF9000295A64 /* UnwindSegue.swift */; }; 1A585F401A7B9530007EEB7D /* KeyboardLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A585F3F1A7B9530007EEB7D /* KeyboardLayoutConstraint.swift */; }; + 1A9F866D1A83C5640098BE6C /* SoundPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9F866C1A83C5640098BE6C /* SoundPlayer.swift */; }; 1AB764641A6E4F070076CD78 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 964117471A5BE90A000E3A5A /* Images.xcassets */; }; 964117411A5BE90A000E3A5A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964117401A5BE90A000E3A5A /* AppDelegate.swift */; }; 964117461A5BE90A000E3A5A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 964117441A5BE90A000E3A5A /* Main.storyboard */; }; @@ -102,6 +103,7 @@ 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 = ""; }; 1AD08AC61A676D5800160D45 /* Spring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spring.swift; sourceTree = ""; }; 1AF3F11A1A6776760090E8F9 /* SpringImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringImageView.swift; sourceTree = ""; }; 1AF3F11B1A6776760090E8F9 /* SpringLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringLabel.swift; sourceTree = ""; }; @@ -221,6 +223,7 @@ 961888DB1A66BF9000295A64 /* ImageLoader.swift */, 1A585F3F1A7B9530007EEB7D /* KeyboardLayoutConstraint.swift */, 961888DF1A66BF9000295A64 /* Misc.swift */, + 1A9F866C1A83C5640098BE6C /* SoundPlayer.swift */, 1AD08AC61A676D5800160D45 /* Spring.swift */, 961888E01A66BF9000295A64 /* SpringAnimation.swift */, 961888E11A66BF9000295A64 /* SpringButton.swift */, @@ -484,6 +487,7 @@ 1A4FDA5A1A6E44A70099D309 /* DesignableTextField.swift in Sources */, 1A4FDA691A6E44A70099D309 /* TransitionManager.swift in Sources */, 1A4FDA5E1A6E44A70099D309 /* ImageLoader.swift in Sources */, + 1A9F866D1A83C5640098BE6C /* SoundPlayer.swift in Sources */, 1A4FDA551A6E44A70099D309 /* BlurView.swift in Sources */, 1A4FDA5D1A6E44A70099D309 /* DesignableTabBarController.swift in Sources */, 1A4FDA591A6E44A70099D309 /* DesignableLabel.swift in Sources */, From df8a07379ee26290ef4e6f15cea58670cd770eef Mon Sep 17 00:00:00 2001 From: 0oneo Date: Sat, 7 Feb 2015 12:15:46 +0800 Subject: [PATCH 011/113] delete duplicate code in changeBall --- SpringApp.xcodeproj/project.pbxproj | 2 ++ SpringApp/SpringViewController.swift | 38 +++++++--------------------- 2 files changed, 11 insertions(+), 29 deletions(-) diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index d156ef2..a74e7e8 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -245,7 +245,9 @@ 1A4FDA431A6E44780099D309 /* SpringTests */, 9641173C1A5BE90A000E3A5A /* Products */, ); + indentWidth = 4; sourceTree = ""; + tabWidth = 4; }; 9641173C1A5BE90A000E3A5A /* Products */ = { isa = PBXGroup; diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index 42362b7..de84e51 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -166,38 +166,18 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView animateView() } - var ballState = 0 + var isBall = false func changeBall() { - switch ballState { - case 1: - let animation = CABasicAnimation() - animation.keyPath = "cornerRadius" - animation.fromValue = 50 - animation.toValue = 10 - animation.duration = 0.2 - ballView.layer.cornerRadius = 10 - ballView.layer.addAnimation(animation, forKey: "radius") - - ballState = 0 - default: - let animation = CABasicAnimation() - animation.keyPath = "cornerRadius" - animation.fromValue = 10 - animation.toValue = 50 - animation.duration = 0.2 - ballView.layer.cornerRadius = 50 - ballView.layer.addAnimation(animation, forKey: "radius") - - ballState++ - } - + isBall = !isBall let animation = CABasicAnimation() - animation.keyPath = "opacity" - animation.fromValue = 1 - animation.toValue = 0 + let halfWidth = ballView.frame.width / 2 + let cornorRadius: CGFloat = isBall ? halfWidth : 10 + animation.keyPath = "cornerRadius" + animation.fromValue = isBall ? 10 : halfWidth + animation.toValue = cornorRadius animation.duration = 0.2 - animation.autoreverses = true - ballView.layer.addAnimation(animation, forKey: "fade") + ballView.layer.cornerRadius = cornorRadius + ballView.layer.addAnimation(animation, forKey: "radius") } @IBAction func shapeButtonPressed(sender: AnyObject) { From 7cd3c257adad94f20146f4aadd90dedfb47f57de Mon Sep 17 00:00:00 2001 From: Piergiuseppe Longo Date: Sun, 8 Feb 2015 14:32:07 +0100 Subject: [PATCH 012/113] Add animate functions to Springable protocol --- Spring/Spring.swift | 5 +++++ 1 file changed, 5 insertions(+) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index e8df7b0..9f3b031 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -45,6 +45,11 @@ import UIKit var layer : CALayer { get } var transform : CGAffineTransform { get set } var alpha : CGFloat { get set } + + func animate() + func animateNext(completion: () -> ()) + func animateTo() + func animateToNext(completion: () -> ()) } public class Spring : NSObject { From 17de954aa0fdf69f24d15c53cfdcf1fa86218840 Mon Sep 17 00:00:00 2001 From: James Tang Date: Tue, 10 Feb 2015 16:12:55 +0800 Subject: [PATCH 013/113] Fixes #23. Consider applicationState for Spring autoStart --- Spring/Spring.swift | 30 +++++++++++++++++++++++++++--- 1 file changed, 27 insertions(+), 3 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index e8df7b0..fa70958 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -50,9 +50,28 @@ import UIKit public class Spring : NSObject { private unowned var view : Springable + private var shouldAnimateAfterActive = false init(_ view: Springable) { self.view = view + super.init() + commonInit() + } + + func commonInit() { + NSNotificationCenter.defaultCenter().addObserver(self, selector: "didBecomeActiveNotification:", name: UIApplicationDidBecomeActiveNotification, object: nil) + } + + func didBecomeActiveNotification(notification: NSNotification) { + if shouldAnimateAfterActive { + alpha = 0 + animate() + shouldAnimateAfterActive = false + } + } + + deinit { + NSNotificationCenter.defaultCenter().removeObserver(self, name: UIApplicationDidBecomeActiveNotification, object: nil) } private var autostart: Bool { set { self.view.autostart = newValue } get { return self.view.autostart }} @@ -350,11 +369,16 @@ public class Spring : NSObject { } public func customDidMoveToWindow() { + if autostart { + + if UIApplication.sharedApplication().applicationState != .Active { + shouldAnimateAfterActive = true + return + } + alpha = 0 - animateFrom = true - animatePreset() - setView {} + animate() } } From f0b8c4cb944b10cd06692b5bf9b6dc61c5b286fb Mon Sep 17 00:00:00 2001 From: James Tang Date: Tue, 10 Feb 2015 16:51:44 +0800 Subject: [PATCH 014/113] Update README and podspec --- README.md | 5 ++++- Spring.podspec | 2 +- 2 files changed, 5 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 401589e..abd9eff 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Drop in the Spring folder to your Xcode project. Or via CocoaPods pre-release: -`pod 'Spring', '~> 1.0.0'` +`pod 'Spring', '~> 1.0.1'` ## Usage with Storyboard In Identity Inspector, connect the UIView to SpringView Class and set the animation properties in Attribute Inspector. @@ -94,6 +94,9 @@ Animations won't autostart when view is reached via performSegueWithIdentifier. - Tutorials available on [Design+Code](https://designcode.io/swiftapp). - [Integrate Spring to existing Objective-C projects](https://medium.com/ios-apprentice/using-swift-in-objective-c-projects-f7e7a09f8be) +## ChangeLog +- At [ChangeLog](https://github.com/MengTo/Spring/wiki/CHANGELOG) wiki page + ## License Spring is released under the MIT license. See LICENSE for details. diff --git a/Spring.podspec b/Spring.podspec index 00d5045..c588b1d 100644 --- a/Spring.podspec +++ b/Spring.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Spring' - s.version = '1.0.0' + s.version = '1.0.1' s.license = 'MIT' s.summary = 'A library to simplify iOS animations in Swift.' s.homepage = 'https://github.com/MengTo/Spring' From d1ba12b2e03dc5ef57669889ee622698a07b87e7 Mon Sep 17 00:00:00 2001 From: 0oneo Date: Sat, 7 Feb 2015 12:16:00 +0800 Subject: [PATCH 015/113] better for reading --- Spring/Misc.swift | 2 +- SpringApp/SpringViewController.swift | 6 +++--- 2 files changed, 4 insertions(+), 4 deletions(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 0fdb931..473dec8 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -157,7 +157,7 @@ public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { let unitFlags = NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitWeekOfYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitSecond let now = NSDate() let earliest = now.earlierDate(date) - let latest = (earliest == now) ? date : now + let latest = now.laterDate(date) let components:NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: nil) if (components.year >= 2) { diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index de84e51..c11d708 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -171,12 +171,12 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView isBall = !isBall let animation = CABasicAnimation() let halfWidth = ballView.frame.width / 2 - let cornorRadius: CGFloat = isBall ? halfWidth : 10 + let cornerRadius: CGFloat = isBall ? halfWidth : 10 animation.keyPath = "cornerRadius" animation.fromValue = isBall ? 10 : halfWidth - animation.toValue = cornorRadius + animation.toValue = cornerRadius animation.duration = 0.2 - ballView.layer.cornerRadius = cornorRadius + ballView.layer.cornerRadius = cornerRadius ballView.layer.addAnimation(animation, forKey: "radius") } From 1baaf211abc95a40050bb021e3c72386cfa0c489 Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 17 Feb 2015 13:07:30 +0800 Subject: [PATCH 016/113] Update README.md --- README.md | 2 ++ 1 file changed, 2 insertions(+) diff --git a/README.md b/README.md index abd9eff..3ec18ae 100644 --- a/README.md +++ b/README.md @@ -90,6 +90,8 @@ Saves you the hassle of adding a line "layer.alpha = 0" in viewDidLoad(). ## Known issue Animations won't autostart when view is reached via performSegueWithIdentifier. +Animations using IBInspectables are currently not working in iOS 7. iOS 8 is supported. We're looking for a fix. Animations in code works for both iOS 7 and 8. + ## Tutorials - Tutorials available on [Design+Code](https://designcode.io/swiftapp). - [Integrate Spring to existing Objective-C projects](https://medium.com/ios-apprentice/using-swift-in-objective-c-projects-f7e7a09f8be) From be0a9b8b87bf90605b902612dd25c2d8711aca25 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Tue, 24 Feb 2015 15:39:08 +0100 Subject: [PATCH 017/113] Added extension for UIColor Added a fromHexString class method --- Spring/UIColor+Spring.swift | 67 +++++++++++++++++++++++++++++++++++++ 1 file changed, 67 insertions(+) create mode 100644 Spring/UIColor+Spring.swift diff --git a/Spring/UIColor+Spring.swift b/Spring/UIColor+Spring.swift new file mode 100644 index 0000000..b581a22 --- /dev/null +++ b/Spring/UIColor+Spring.swift @@ -0,0 +1,67 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 Giacomo Piva (me@giacomopiva.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import UIKit + +extension UIColor { + + // This method returns a UIColor from a Hex string (eg. #ffffff) + // Usage: let whiteColor = UIColor.fromHexString("#ffffff") + // + class func fromHexString(hexString:String) -> UIColor { + var str:String = hexString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet() as NSCharacterSet) + var rgb:UInt32 = 0 + str = str.uppercaseString + if (str.hasPrefix("#")) { + str = str.substringFromIndex(advance(str.startIndex, 1)) + } + if (countElements(str) != 6) { + if countElements(str) == 3 { + str = "".stringByAppendingString("\(str[0])") + .stringByAppendingString("\(str[0])") + .stringByAppendingString("\(str[1])") + .stringByAppendingString("\(str[1])") + .stringByAppendingString("\(str[2])") + .stringByAppendingString("\(str[2])") + } else { + return UIColor.grayColor() + } + } + NSScanner(string: str).scanHexInt(&rgb) + return UIColor( + red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, + green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, + blue: CGFloat(rgb & 0x0000FF) / 255.0, + alpha: CGFloat(1.0) + ) + } +} + +extension String { + + // "abcde"[0] === 'a' + // + subscript (i: Int) -> Character { + return self[advance(self.startIndex, i)] + } + +} From 5f406460a676f5f3a2d7ff8d4eb0393f08c9b58b Mon Sep 17 00:00:00 2001 From: Giacomo Date: Wed, 25 Feb 2015 13:34:09 +0100 Subject: [PATCH 018/113] Deleted UIColor extension Duplicated funcionality --- Spring/UIColor+Spring.swift | 67 ------------------------------------- 1 file changed, 67 deletions(-) delete mode 100644 Spring/UIColor+Spring.swift diff --git a/Spring/UIColor+Spring.swift b/Spring/UIColor+Spring.swift deleted file mode 100644 index b581a22..0000000 --- a/Spring/UIColor+Spring.swift +++ /dev/null @@ -1,67 +0,0 @@ -// The MIT License (MIT) -// -// Copyright (c) 2015 Giacomo Piva (me@giacomopiva.com) -// -// Permission is hereby granted, free of charge, to any person obtaining a copy -// of this software and associated documentation files (the "Software"), to deal -// in the Software without restriction, including without limitation the rights -// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell -// copies of the Software, and to permit persons to whom the Software is -// furnished to do so, subject to the following conditions: -// -// The above copyright notice and this permission notice shall be included in all -// copies or substantial portions of the Software. -// -// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR -// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, -// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE -// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER -// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, -// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE -// SOFTWARE. - -import UIKit - -extension UIColor { - - // This method returns a UIColor from a Hex string (eg. #ffffff) - // Usage: let whiteColor = UIColor.fromHexString("#ffffff") - // - class func fromHexString(hexString:String) -> UIColor { - var str:String = hexString.stringByTrimmingCharactersInSet(NSCharacterSet.whitespaceAndNewlineCharacterSet() as NSCharacterSet) - var rgb:UInt32 = 0 - str = str.uppercaseString - if (str.hasPrefix("#")) { - str = str.substringFromIndex(advance(str.startIndex, 1)) - } - if (countElements(str) != 6) { - if countElements(str) == 3 { - str = "".stringByAppendingString("\(str[0])") - .stringByAppendingString("\(str[0])") - .stringByAppendingString("\(str[1])") - .stringByAppendingString("\(str[1])") - .stringByAppendingString("\(str[2])") - .stringByAppendingString("\(str[2])") - } else { - return UIColor.grayColor() - } - } - NSScanner(string: str).scanHexInt(&rgb) - return UIColor( - red: CGFloat((rgb & 0xFF0000) >> 16) / 255.0, - green: CGFloat((rgb & 0x00FF00) >> 8) / 255.0, - blue: CGFloat(rgb & 0x0000FF) / 255.0, - alpha: CGFloat(1.0) - ) - } -} - -extension String { - - // "abcde"[0] === 'a' - // - subscript (i: Int) -> Character { - return self[advance(self.startIndex, i)] - } - -} From d408b9815ee25067dfb815a155d9192c0b666968 Mon Sep 17 00:00:00 2001 From: Giacomo Date: Wed, 25 Feb 2015 13:36:17 +0100 Subject: [PATCH 019/113] Improved existing UIColor extension Now init with hex string is #-safe --- Spring/Misc.swift | 58 ++++++++++++++-------------- SpringApp/SpringViewController.swift | 2 +- 2 files changed, 30 insertions(+), 30 deletions(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 473dec8..3fcc61c 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -62,40 +62,40 @@ public extension UIColor { var green: CGFloat = 0.0 var blue: CGFloat = 0.0 var alpha: CGFloat = 1.0 + var hex: String = hex if hex.hasPrefix("#") { let index = advance(hex.startIndex, 1) - let hex = hex.substringFromIndex(index) - let scanner = NSScanner(string: hex) - var hexValue: CUnsignedLongLong = 0 - if scanner.scanHexLongLong(&hexValue) { - switch (countElements(hex)) { - case 3: - red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 - green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 - blue = CGFloat(hexValue & 0x00F) / 15.0 - case 4: - red = CGFloat((hexValue & 0xF000) >> 12) / 15.0 - green = CGFloat((hexValue & 0x0F00) >> 8) / 15.0 - blue = CGFloat((hexValue & 0x00F0) >> 4) / 15.0 - alpha = CGFloat(hexValue & 0x000F) / 15.0 - case 6: - red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0 - green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0 - blue = CGFloat(hexValue & 0x0000FF) / 255.0 - case 8: - red = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0 - green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0 - blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0 - alpha = CGFloat(hexValue & 0x000000FF) / 255.0 - default: - print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8") - } - } else { - println("Scan hex error") + hex = hex.substringFromIndex(index) + } + + let scanner = NSScanner(string: hex) + var hexValue: CUnsignedLongLong = 0 + if scanner.scanHexLongLong(&hexValue) { + switch (countElements(hex)) { + case 3: + red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 + green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 + blue = CGFloat(hexValue & 0x00F) / 15.0 + case 4: + red = CGFloat((hexValue & 0xF000) >> 12) / 15.0 + green = CGFloat((hexValue & 0x0F00) >> 8) / 15.0 + blue = CGFloat((hexValue & 0x00F0) >> 4) / 15.0 + alpha = CGFloat(hexValue & 0x000F) / 15.0 + case 6: + red = CGFloat((hexValue & 0xFF0000) >> 16) / 255.0 + green = CGFloat((hexValue & 0x00FF00) >> 8) / 255.0 + blue = CGFloat(hexValue & 0x0000FF) / 255.0 + case 8: + red = CGFloat((hexValue & 0xFF000000) >> 24) / 255.0 + green = CGFloat((hexValue & 0x00FF0000) >> 16) / 255.0 + blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0 + alpha = CGFloat(hexValue & 0x000000FF) / 255.0 + default: + print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8") } } else { - print("Invalid RGB string, missing '#' as prefix") + println("Scan hex error") } self.init(red:red, green:green, blue:blue, alpha:alpha) } diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index c11d708..1d8a9c0 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -156,7 +156,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView @IBAction func ballButtonPressed(sender: AnyObject) { UIView.animateWithDuration(0.1, animations: { - self.ballView.backgroundColor = UIColor(hex: "#69DBFF") + self.ballView.backgroundColor = UIColor(hex: "69DBFF") }, completion: { finished in UIView.animateWithDuration(0.5, animations: { self.ballView.backgroundColor = UIColor(hex: "#279CEB") From 24b9d643463d3db175224d55a5bb06fc3f1dc835 Mon Sep 17 00:00:00 2001 From: James Tang Date: Mon, 2 Mar 2015 00:05:09 +0800 Subject: [PATCH 020/113] Added AsyncImageView and AsyncButton --- Spring/AsyncButton.swift | 51 ++++++++++++++++++++++++++++ Spring/AsyncImageView.swift | 52 +++++++++++++++++++++++++++++ SpringApp.xcodeproj/project.pbxproj | 8 +++++ 3 files changed, 111 insertions(+) create mode 100644 Spring/AsyncButton.swift create mode 100644 Spring/AsyncImageView.swift diff --git a/Spring/AsyncButton.swift b/Spring/AsyncButton.swift new file mode 100644 index 0000000..5b9af8c --- /dev/null +++ b/Spring/AsyncButton.swift @@ -0,0 +1,51 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 James Tang (j@jamztang.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import UIKit +import Spring + +public class AsyncButton: UIButton { + + private var imageURL = [UInt:NSURL]() + private var placeholderImage = [UInt:UIImage]() + + + public func setImageURL(url: NSURL?, placeholderImage placeholder:UIImage?, forState state:UIControlState) { + + imageURL[state.rawValue] = url + placeholderImage[state.rawValue] = placeholder + + if let urlString = url?.absoluteString { + ImageLoader.sharedLoader.imageForUrl(urlString) { [weak self] image, url in + + if let strongSelf = self { + dispatch_async(dispatch_get_main_queue(), { () -> Void in + if strongSelf.imageURL[state.rawValue]?.absoluteString == url { + strongSelf.setImage(image, forState: state) + } + }) + } + } + } + } + +} diff --git a/Spring/AsyncImageView.swift b/Spring/AsyncImageView.swift new file mode 100644 index 0000000..9a91d7a --- /dev/null +++ b/Spring/AsyncImageView.swift @@ -0,0 +1,52 @@ +// The MIT License (MIT) +// +// Copyright (c) 2015 James Tang (j@jamztang.com) +// +// Permission is hereby granted, free of charge, to any person obtaining a copy +// of this software and associated documentation files (the "Software"), to deal +// in the Software without restriction, including without limitation the rights +// to use, copy, modify, merge, publish, distribute, sublicense, and/or sell +// copies of the Software, and to permit persons to whom the Software is +// furnished to do so, subject to the following conditions: +// +// The above copyright notice and this permission notice shall be included in all +// copies or substantial portions of the Software. +// +// THE SOFTWARE IS PROVIDED "AS IS", WITHOUT WARRANTY OF ANY KIND, EXPRESS OR +// IMPLIED, INCLUDING BUT NOT LIMITED TO THE WARRANTIES OF MERCHANTABILITY, +// FITNESS FOR A PARTICULAR PURPOSE AND NONINFRINGEMENT. IN NO EVENT SHALL THE +// AUTHORS OR COPYRIGHT HOLDERS BE LIABLE FOR ANY CLAIM, DAMAGES OR OTHER +// LIABILITY, WHETHER IN AN ACTION OF CONTRACT, TORT OR OTHERWISE, ARISING FROM, +// OUT OF OR IN CONNECTION WITH THE SOFTWARE OR THE USE OR OTHER DEALINGS IN THE +// SOFTWARE. + +import UIKit +import Spring + +public class AsyncImageView: UIImageView { + + public var placeholderImage : UIImage? + + public var url : NSURL? { + didSet { + self.image = placeholderImage + if let urlString = url?.absoluteString { + ImageLoader.sharedLoader.imageForUrl(urlString) { [weak self] image, url in + if let strongSelf = self { + dispatch_async(dispatch_get_main_queue(), { () -> Void in + if strongSelf.url?.absoluteString == url { + strongSelf.image = image + } + }) + } + } + } + } + } + + public func setURL(url: NSURL?, placeholderImage: UIImage?) { + self.placeholderImage = placeholderImage + self.url = url + } + +} diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index 49a0856..a6a1c09 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -37,6 +37,8 @@ 1A4FDA6B1A6E44A70099D309 /* UnwindSegue.swift in Sources */ = {isa = PBXBuildFile; fileRef = 961888E51A66BF9000295A64 /* UnwindSegue.swift */; }; 1A585F401A7B9530007EEB7D /* KeyboardLayoutConstraint.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A585F3F1A7B9530007EEB7D /* KeyboardLayoutConstraint.swift */; }; 1A9F866D1A83C5640098BE6C /* SoundPlayer.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1A9F866C1A83C5640098BE6C /* SoundPlayer.swift */; }; + 1AA7E1831AA36EFF00762D75 /* AsyncImageView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AA7E1811AA36EFF00762D75 /* AsyncImageView.swift */; }; + 1AA7E1841AA36EFF00762D75 /* AsyncButton.swift in Sources */ = {isa = PBXBuildFile; fileRef = 1AA7E1821AA36EFF00762D75 /* AsyncButton.swift */; }; 1AB764641A6E4F070076CD78 /* Images.xcassets in Resources */ = {isa = PBXBuildFile; fileRef = 964117471A5BE90A000E3A5A /* Images.xcassets */; }; 964117411A5BE90A000E3A5A /* AppDelegate.swift in Sources */ = {isa = PBXBuildFile; fileRef = 964117401A5BE90A000E3A5A /* AppDelegate.swift */; }; 964117461A5BE90A000E3A5A /* Main.storyboard in Resources */ = {isa = PBXBuildFile; fileRef = 964117441A5BE90A000E3A5A /* Main.storyboard */; }; @@ -104,6 +106,8 @@ 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 = ""; }; + 1AA7E1821AA36EFF00762D75 /* AsyncButton.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AsyncButton.swift; sourceTree = ""; }; 1AD08AC61A676D5800160D45 /* Spring.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = Spring.swift; sourceTree = ""; }; 1AF3F11A1A6776760090E8F9 /* SpringImageView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringImageView.swift; sourceTree = ""; }; 1AF3F11B1A6776760090E8F9 /* SpringLabel.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = SpringLabel.swift; sourceTree = ""; }; @@ -210,6 +214,8 @@ 961888D21A66BF9000295A64 /* Spring */ = { isa = PBXGroup; children = ( + 1AA7E1821AA36EFF00762D75 /* AsyncButton.swift */, + 1AA7E1811AA36EFF00762D75 /* AsyncImageView.swift */, 1A4FDA2A1A6E44270099D309 /* LoadingView.swift */, 1A4FDA2B1A6E44270099D309 /* LoadingView.xib */, 961888D31A66BF9000295A64 /* BlurView.swift */, @@ -491,12 +497,14 @@ 1A4FDA5E1A6E44A70099D309 /* ImageLoader.swift in Sources */, 1A9F866D1A83C5640098BE6C /* SoundPlayer.swift in Sources */, 1A4FDA551A6E44A70099D309 /* BlurView.swift in Sources */, + 1AA7E1841AA36EFF00762D75 /* AsyncButton.swift in Sources */, 1A4FDA5D1A6E44A70099D309 /* DesignableTabBarController.swift in Sources */, 1A4FDA591A6E44A70099D309 /* DesignableLabel.swift in Sources */, 1A4FDA661A6E44A70099D309 /* SpringTextField.swift in Sources */, 1A4FDA631A6E44A70099D309 /* SpringButton.swift in Sources */, 1A4FDA621A6E44A70099D309 /* SpringAnimation.swift in Sources */, 1A585F401A7B9530007EEB7D /* KeyboardLayoutConstraint.swift in Sources */, + 1AA7E1831AA36EFF00762D75 /* AsyncImageView.swift in Sources */, 1A4FDA6B1A6E44A70099D309 /* UnwindSegue.swift in Sources */, 1A4FDA681A6E44A70099D309 /* SpringView.swift in Sources */, 1A4FDA6A1A6E44A70099D309 /* TransitionZoom.swift in Sources */, From b776a6dca3b28df7a2c5872fa31d5c96bd0ba90e Mon Sep 17 00:00:00 2001 From: Nolan Waite Date: Mon, 9 Mar 2015 12:03:28 -0300 Subject: [PATCH 021/113] Delete extraneous imports Spring. They prevent building Spring by dragging the files into your Xcode project, because that won't make a module called Spring. --- Spring/AsyncButton.swift | 1 - Spring/AsyncImageView.swift | 1 - 2 files changed, 2 deletions(-) diff --git a/Spring/AsyncButton.swift b/Spring/AsyncButton.swift index 5b9af8c..d92937c 100644 --- a/Spring/AsyncButton.swift +++ b/Spring/AsyncButton.swift @@ -21,7 +21,6 @@ // SOFTWARE. import UIKit -import Spring public class AsyncButton: UIButton { diff --git a/Spring/AsyncImageView.swift b/Spring/AsyncImageView.swift index 9a91d7a..0e20cdf 100644 --- a/Spring/AsyncImageView.swift +++ b/Spring/AsyncImageView.swift @@ -21,7 +21,6 @@ // SOFTWARE. import UIKit -import Spring public class AsyncImageView: UIImageView { From 3fe49b5a71ca3c9f28cc2fbc0ea5089df4d13a45 Mon Sep 17 00:00:00 2001 From: naoyashiga Date: Sun, 15 Mar 2015 16:33:23 +0900 Subject: [PATCH 022/113] add easing functions --- Spring/Spring.swift | 48 ++++++++++++++++++++++++++++ SpringApp/SpringViewController.swift | 2 +- 2 files changed, 49 insertions(+), 1 deletion(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 77a0529..628ecd8 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -318,6 +318,54 @@ public class Spring : NSObject { return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) 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) default: return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault) } diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index c11d708..7d163d5 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -143,7 +143,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView "zoomIn", "zoomOut", "flash", - ], ["spring", "linear", "easeIn", "easeOut", "easeInOut"]] + ], ["spring", "linear", "easeIn", "easeOut", "easeInOut","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() From df41b1ca42fb8177597243063577d8fd2094a01b Mon Sep 17 00:00:00 2001 From: James Tang Date: Sun, 22 Mar 2015 23:27:41 +0800 Subject: [PATCH 023/113] Refs MengTo/DesignerNewsApp#93 remove global dateformatter to be more safe --- Spring/Misc.swift | 22 ++++++---------------- 1 file changed, 6 insertions(+), 16 deletions(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 3fcc61c..ad0cc05 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -115,26 +115,16 @@ public func UIColorFromRGB(rgbValue: UInt) -> UIColor { ) } -var dateFormatter : NSDateFormatter? - public func stringFromDate(date: NSDate, format: String) -> String { - - if dateFormatter == nil { - dateFormatter = NSDateFormatter() - } - - dateFormatter!.dateFormat = format - return dateFormatter!.stringFromDate(date) + let dateFormatter = NSDateFormatter() + dateFormatter.dateFormat = format + return dateFormatter.stringFromDate(date) } public func dateFromString(date: String, format: String) -> NSDate { - - if dateFormatter == nil { - dateFormatter = NSDateFormatter() - } - - dateFormatter!.dateFormat = format - return dateFormatter!.dateFromString(date)! + let dateFormatter = NSDateFormatter() + dateFormatter.dateFormat = format + return dateFormatter.dateFromString(date)! } public func randomStringWithLength (len : Int) -> NSString { From 4f766df7196cb2a4dfdca088755571c20b4ca2b6 Mon Sep 17 00:00:00 2001 From: James Tang Date: Tue, 24 Mar 2015 14:34:17 +0800 Subject: [PATCH 024/113] Prevent dateFromString crashing if date can actually be nil --- Spring/Misc.swift | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index ad0cc05..4b6e8de 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -124,7 +124,11 @@ public func stringFromDate(date: NSDate, format: String) -> String { public func dateFromString(date: String, format: String) -> NSDate { let dateFormatter = NSDateFormatter() dateFormatter.dateFormat = format - return dateFormatter.dateFromString(date)! + if let date = dateFormatter.dateFromString(date) { + return date + } else { + return NSDate(timeIntervalSince1970: 0) + } } public func randomStringWithLength (len : Int) -> NSString { From 339a16e871d180624e91721b3028324300f16f2a Mon Sep 17 00:00:00 2001 From: Meng To Date: Thu, 26 Mar 2015 19:16:11 +0900 Subject: [PATCH 025/113] Small fix for timeAgoSinceDate function --- Spring/Misc.swift | 6 +++--- 1 file changed, 3 insertions(+), 3 deletions(-) diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 473dec8..ce1404c 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -169,12 +169,12 @@ public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { return "1y" } } else if (components.month >= 2) { - return "\(components.month)" + return "\(components.month * 4)w" } else if (components.month >= 1){ if (numericDates){ - return "1M" + return "4w" } else { - return "1M" + return "4w" } } else if (components.weekOfYear >= 2) { return "\(components.weekOfYear)w" From 0a906d440c8e7f5918aa53fd3d4797c0877c44fe Mon Sep 17 00:00:00 2001 From: Meng To Date: Fri, 27 Mar 2015 01:04:02 +0900 Subject: [PATCH 026/113] AutoTextView This will help dealing with TextView's Auto Layout. --- Spring/AutoTextView.swift | 24 ++++++++++++++++++++++++ SpringApp.xcodeproj/project.pbxproj | 4 ++++ 2 files changed, 28 insertions(+) create mode 100644 Spring/AutoTextView.swift diff --git a/Spring/AutoTextView.swift b/Spring/AutoTextView.swift new file mode 100644 index 0000000..e1b3e31 --- /dev/null +++ b/Spring/AutoTextView.swift @@ -0,0 +1,24 @@ +// +// AutoTextView.swift +// SpringApp +// +// Created by Meng To on 2015-03-27. +// Copyright (c) 2015 Meng To. All rights reserved. +// + +import UIKit + +class AutoTextView: UITextView { + override func intrinsicContentSize() -> CGSize { + var size = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max)) + size.width = self.frame.size.width + if text.length == 0 { + size.height = 0 + } + + contentInset = UIEdgeInsetsMake(-4, -4, -4, -4) + layoutIfNeeded() + + return size + } +} \ No newline at end of file diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index a6a1c09..a16045e 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -48,6 +48,7 @@ 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 */; }; + 96C5F4621AC464C800BB8A18 /* AutoTextView.swift in Sources */ = {isa = PBXBuildFile; fileRef = 96C5F4611AC464C800BB8A18 /* AutoTextView.swift */; }; /* End PBXBuildFile section */ /* Begin PBXContainerItemProxy section */ @@ -141,6 +142,7 @@ 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 = ""; }; 969775D31A6AD6AC009B4B79 /* DesignableTabBarController.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = DesignableTabBarController.swift; sourceTree = ""; }; + 96C5F4611AC464C800BB8A18 /* AutoTextView.swift */ = {isa = PBXFileReference; fileEncoding = 4; lastKnownFileType = sourcecode.swift; path = AutoTextView.swift; sourceTree = ""; }; /* End PBXFileReference section */ /* Begin PBXFrameworksBuildPhase section */ @@ -216,6 +218,7 @@ children = ( 1AA7E1821AA36EFF00762D75 /* AsyncButton.swift */, 1AA7E1811AA36EFF00762D75 /* AsyncImageView.swift */, + 96C5F4611AC464C800BB8A18 /* AutoTextView.swift */, 1A4FDA2A1A6E44270099D309 /* LoadingView.swift */, 1A4FDA2B1A6E44270099D309 /* LoadingView.xib */, 961888D31A66BF9000295A64 /* BlurView.swift */, @@ -530,6 +533,7 @@ 9641178D1A5BEC6F000E3A5A /* CodeViewController.swift in Sources */, 9641178C1A5BEC6F000E3A5A /* OptionsViewController.swift in Sources */, 9641178B1A5BEC6F000E3A5A /* SpringViewController.swift in Sources */, + 96C5F4621AC464C800BB8A18 /* AutoTextView.swift in Sources */, ); runOnlyForDeploymentPostprocessing = 0; }; From ad95955ddd4c5f1e86e9067a943f0023cd242df0 Mon Sep 17 00:00:00 2001 From: James Tang Date: Fri, 27 Mar 2015 13:15:02 +0800 Subject: [PATCH 027/113] Update Podspec (1.0.2) to include resource fixes #44 --- Spring.podspec | 3 ++- 1 file changed, 2 insertions(+), 1 deletion(-) diff --git a/Spring.podspec b/Spring.podspec index c588b1d..37b387a 100644 --- a/Spring.podspec +++ b/Spring.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Spring' - s.version = '1.0.1' + s.version = '1.0.2' s.license = 'MIT' s.summary = 'A library to simplify iOS animations in Swift.' s.homepage = 'https://github.com/MengTo/Spring' @@ -9,4 +9,5 @@ Pod::Spec.new do |s| s.requires_arc = true s.ios.deployment_target = '8.0' s.source_files = 'Spring/*.swift' + s.resources = ['Spring/*.xib', 'SpringApp/*.xcassets'] end From 28e8d9052d4a0f0c9a940c8129ec2db37a2bc7fd Mon Sep 17 00:00:00 2001 From: James Tang Date: Sun, 29 Mar 2015 14:31:11 +0800 Subject: [PATCH 028/113] Make SpringApp schema to default --- .../xcshareddata/SpringApp.xccheckout | 41 ++++++ .../xcshareddata/xcschemes/SpringApp.xcscheme | 136 ++++++++++++++++++ 2 files changed, 177 insertions(+) create mode 100644 SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout create mode 100644 SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme diff --git a/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout b/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout new file mode 100644 index 0000000..7c00884 --- /dev/null +++ b/SpringApp.xcodeproj/project.xcworkspace/xcshareddata/SpringApp.xccheckout @@ -0,0 +1,41 @@ + + + + + IDESourceControlProjectFavoriteDictionaryKey + + IDESourceControlProjectIdentifier + 90BE4A8A-3AD7-483D-B9EA-ED8463875CE6 + IDESourceControlProjectName + SpringApp + IDESourceControlProjectOriginsDictionary + + 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E + github.com:MengTo/Spring.git + + IDESourceControlProjectPath + SpringApp.xcodeproj + IDESourceControlProjectRelativeInstallPathDictionary + + 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E + ../.. + + IDESourceControlProjectURL + github.com:MengTo/Spring.git + IDESourceControlProjectVersion + 111 + IDESourceControlProjectWCCIdentifier + 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E + IDESourceControlProjectWCConfigurations + + + IDESourceControlRepositoryExtensionIdentifierKey + public.vcs.git + IDESourceControlWCCIdentifierKey + 71F5D8D885CFF6BD7151066D7BFF25CC48A5235E + IDESourceControlWCCName + Spring + + + + diff --git a/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme b/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme new file mode 100644 index 0000000..06c9955 --- /dev/null +++ b/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme @@ -0,0 +1,136 @@ + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + + From c96f45b659c3842857068a5aa1b46f2b18cd4a0d Mon Sep 17 00:00:00 2001 From: Chao Ruan Date: Tue, 31 Mar 2015 22:20:26 +1100 Subject: [PATCH 029/113] Support swift 1.2 --- Spring/DesignableTabBarController.swift | 22 +++++++-------- Spring/LoadingView.swift | 2 +- Spring/Misc.swift | 4 +-- Spring/Spring.swift | 37 +++++++++++++------------ SpringApp/OptionsViewController.swift | 12 ++++---- SpringApp/SpringViewController.swift | 18 ++++++------ 6 files changed, 48 insertions(+), 47 deletions(-) diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index 5637f80..bbaa6f4 100644 --- a/Spring/DesignableTabBarController.swift +++ b/Spring/DesignableTabBarController.swift @@ -46,8 +46,8 @@ import UIKit @IBInspectable var firstSelectedImage: UIImage? { didSet { - if let image = firstSelectedImage? { - var tabBarItems = self.tabBar.items as [UITabBarItem] + if let image = firstSelectedImage { + var tabBarItems = self.tabBar.items as! [UITabBarItem] tabBarItems[0].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -55,8 +55,8 @@ import UIKit @IBInspectable var secondSelectedImage: UIImage? { didSet { - if let image = secondSelectedImage? { - var tabBarItems = self.tabBar.items as [UITabBarItem] + if let image = secondSelectedImage { + var tabBarItems = self.tabBar.items as! [UITabBarItem] tabBarItems[1].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -64,8 +64,8 @@ import UIKit @IBInspectable var thirdSelectedImage: UIImage? { didSet { - if let image = thirdSelectedImage? { - var tabBarItems = self.tabBar.items as [UITabBarItem] + if let image = thirdSelectedImage { + var tabBarItems = self.tabBar.items as! [UITabBarItem] tabBarItems[2].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -73,8 +73,8 @@ import UIKit @IBInspectable var fourthSelectedImage: UIImage? { didSet { - if let image = fourthSelectedImage? { - var tabBarItems = self.tabBar.items as [UITabBarItem] + if let image = fourthSelectedImage { + var tabBarItems = self.tabBar.items as! [UITabBarItem] tabBarItems[3].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -82,8 +82,8 @@ import UIKit @IBInspectable var fifthSelectedImage: UIImage? { didSet { - if let image = fifthSelectedImage? { - var tabBarItems = self.tabBar.items as [UITabBarItem] + if let image = fifthSelectedImage { + var tabBarItems = self.tabBar.items as! [UITabBarItem] tabBarItems[4].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -92,7 +92,7 @@ import UIKit override func viewDidLoad() { super.viewDidLoad() - for item in self.tabBar.items as [UITabBarItem] { + for item in self.tabBar.items as! [UITabBarItem] { if let image = item.image { item.image = image.imageWithColor(self.normalTint).imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) } diff --git a/Spring/LoadingView.swift b/Spring/LoadingView.swift index 0e013a7..8884037 100644 --- a/Spring/LoadingView.swift +++ b/Spring/LoadingView.swift @@ -37,7 +37,7 @@ public class LoadingView: UIView { } class func designCodeLoadingView() -> UIView { - return NSBundle(forClass: self).loadNibNamed("LoadingView", owner: self, options: nil)[0] as UIView + return NSBundle(forClass: self).loadNibNamed("LoadingView", owner: self, options: nil)[0] as! UIView } } diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 7b9ed9d..b537590 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -23,7 +23,7 @@ import UIKit public extension String { - public var length: Int { return countElements(self) } + public var length: Int { return count(self) } public func toURL() -> NSURL? { return NSURL(string: self) @@ -72,7 +72,7 @@ public extension UIColor { let scanner = NSScanner(string: hex) var hexValue: CUnsignedLongLong = 0 if scanner.scanHexLongLong(&hexValue) { - switch (countElements(hex)) { + switch (count(hex)) { case 3: red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 628ecd8..588f2e4 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -452,30 +452,31 @@ public class Spring : NSObject { initialSpringVelocity: velocity, options: getAnimationOptions(curve), animations: { [weak self] in - if let _self = self - { - if _self.animateFrom { - _self.transform = CGAffineTransformIdentity - _self.alpha = 1 - } - else { - let translate = CGAffineTransformMakeTranslation(_self.x, _self.y) - let scale = CGAffineTransformMakeScale(_self.scaleX, _self.scaleY) - let rotate = CGAffineTransformMakeRotation(_self.rotate) - let translateAndScale = CGAffineTransformConcat(translate, scale) - _self.transform = CGAffineTransformConcat(rotate, translateAndScale) - - _self.alpha = _self.opacity - } + if let _self = self + { + if _self.animateFrom { + _self.transform = CGAffineTransformIdentity + _self.alpha = 1 + } + else { + let translate = CGAffineTransformMakeTranslation(_self.x, _self.y) + let scale = CGAffineTransformMakeScale(_self.scaleX, _self.scaleY) + let rotate = CGAffineTransformMakeRotation(_self.rotate) + let translateAndScale = CGAffineTransformConcat(translate, scale) + _self.transform = CGAffineTransformConcat(rotate, translateAndScale) + _self.alpha = _self.opacity } - }, { [weak self] finished in + } + + }, completion: { [weak self] finished in completion() self?.resetAll() - - }) + + }) + } func reset() { diff --git a/SpringApp/OptionsViewController.swift b/SpringApp/OptionsViewController.swift index 1cba77c..251a54a 100644 --- a/SpringApp/OptionsViewController.swift +++ b/SpringApp/OptionsViewController.swift @@ -68,37 +68,37 @@ class OptionsViewController: UIViewController { } @IBAction func dampingSliderChanged(sender: AnyObject) { - selectedDamping = sender.valueForKey("value") as CGFloat + selectedDamping = sender.valueForKey("value") as! CGFloat delegate?.dampingSliderChanged(sender) dampingLabel.text = getString("Damping", value: selectedDamping) } @IBAction func velocitySliderChanged(sender: AnyObject) { - selectedVelocity = sender.valueForKey("value") as CGFloat + selectedVelocity = sender.valueForKey("value") as! CGFloat delegate?.velocitySliderChanged(sender) velocityLabel.text = getString("Velocity", value: selectedVelocity) } @IBAction func scaleSliderChanged(sender: AnyObject) { - selectedScale = sender.valueForKey("value") as CGFloat + selectedScale = sender.valueForKey("value") as! CGFloat delegate?.scaleSliderChanged(sender) scaleLabel.text = getString("Scale", value: selectedScale) } @IBAction func xSliderChanged(sender: AnyObject) { - selectedX = sender.valueForKey("value") as CGFloat + selectedX = sender.valueForKey("value") as! CGFloat delegate?.xSliderChanged(sender) xLabel.text = getString("X", value: selectedX) } @IBAction func ySliderChanged(sender: AnyObject) { - selectedY = sender.valueForKey("value") as CGFloat + selectedY = sender.valueForKey("value") as! CGFloat delegate?.ySliderChanged(sender) yLabel.text = getString("Y", value: selectedY) } @IBAction func rotateSliderChanged(sender: AnyObject) { - selectedRotate = sender.valueForKey("value") as CGFloat + selectedRotate = sender.valueForKey("value") as! CGFloat delegate?.rotateSliderChanged(sender) rotateLabel.text = getString("Rotate", value: selectedRotate) } diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index e38d8bd..a401517 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -35,48 +35,48 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView var selectedRotate: CGFloat = 0 @IBAction func forceSliderChanged(sender: AnyObject) { - selectedForce = sender.valueForKey("value") as CGFloat + selectedForce = sender.valueForKey("value") as! CGFloat animateView() forceLabel.text = String(format: "Force: %.1f", Double(selectedForce)) } @IBAction func durationSliderChanged(sender: AnyObject) { - selectedDuration = sender.valueForKey("value") as CGFloat + selectedDuration = sender.valueForKey("value") as! CGFloat animateView() durationLabel.text = String(format: "Duration: %.1f", Double(selectedDuration)) } @IBAction func delaySliderChanged(sender: AnyObject) { - selectedDelay = sender.valueForKey("value") as CGFloat + selectedDelay = sender.valueForKey("value") as! CGFloat animateView() delayLabel.text = String(format: "Delay: %.1f", Double(selectedDelay)) } func dampingSliderChanged(sender: AnyObject) { - selectedDamping = sender.valueForKey("value") as CGFloat + selectedDamping = sender.valueForKey("value") as! CGFloat animateView() } func velocitySliderChanged(sender: AnyObject) { - selectedVelocity = sender.valueForKey("value") as CGFloat + selectedVelocity = sender.valueForKey("value") as! CGFloat animateView() } func scaleSliderChanged(sender: AnyObject) { - selectedScale = sender.valueForKey("value") as CGFloat + selectedScale = sender.valueForKey("value") as! CGFloat animateView() } func xSliderChanged(sender: AnyObject) { - selectedX = sender.valueForKey("value") as CGFloat + selectedX = sender.valueForKey("value") as! CGFloat animateView() } func ySliderChanged(sender: AnyObject) { - selectedY = sender.valueForKey("value") as CGFloat + selectedY = sender.valueForKey("value") as! CGFloat animateView() } func rotateSliderChanged(sender: AnyObject) { - selectedRotate = sender.valueForKey("value") as CGFloat + selectedRotate = sender.valueForKey("value") as! CGFloat animateView() } From 89a0425b4b046751b5be2214c882cc53bd5bdc34 Mon Sep 17 00:00:00 2001 From: Meng To Date: Thu, 9 Apr 2015 01:22:01 +0900 Subject: [PATCH 030/113] Fix animateTo completion for some animations --- Spring/Spring.swift | 1 + 1 file changed, 1 insertion(+) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 628ecd8..bdb7246 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -103,6 +103,7 @@ public class Spring : NSObject { private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } func animatePreset() { + alpha = 0.99 if animation == "" { return } From c51c19224cc717a4fb8980a22782892a88d08508 Mon Sep 17 00:00:00 2001 From: Meng To Date: Fri, 10 Apr 2015 20:29:25 +0900 Subject: [PATCH 031/113] Fix warning for 1.2 --- Spring/DesignableTabBarController.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index bbaa6f4..fc57f65 100644 --- a/Spring/DesignableTabBarController.swift +++ b/Spring/DesignableTabBarController.swift @@ -33,7 +33,7 @@ import UIKit @IBInspectable var selectedTint: UIColor = UIColor.clearColor() { didSet { - UITabBar.appearance().selectedImageTintColor = selectedTint + UITabBar.appearance().tintColor = selectedTint UITabBarItem.appearance().setTitleTextAttributes([NSForegroundColorAttributeName: selectedTint], forState:UIControlState.Selected) } } From 096a1dd26a692c19107f4a61c4a88c725056652e Mon Sep 17 00:00:00 2001 From: jasdev Date: Sat, 11 Apr 2015 15:27:35 -0700 Subject: [PATCH 032/113] README Pod update and whitespace --- README.md | 11 +++++------ 1 file changed, 5 insertions(+), 6 deletions(-) diff --git a/README.md b/README.md index 3ec18ae..0db91ec 100644 --- a/README.md +++ b/README.md @@ -3,8 +3,8 @@ ## Installation Drop in the Spring folder to your Xcode project. -Or via CocoaPods pre-release: -`pod 'Spring', '~> 1.0.1'` +Or via CocoaPods: +`pod 'Spring', '~> 1.0.2'` ## Usage with Storyboard In Identity Inspector, connect the UIView to SpringView Class and set the animation properties in Attribute Inspector. @@ -61,9 +61,9 @@ In Identity Inspector, connect the UIView to SpringView Class and set the animat ## Curve spring - linear - easeIn - easeOut + linear + easeIn + easeOut easeInOut ## Properties @@ -102,4 +102,3 @@ Animations using IBInspectables are currently not working in iOS 7. iOS 8 is sup ## License Spring is released under the MIT license. See LICENSE for details. - From e4c8c09b96b68d1bc6dc64f3c388f018748ad33a Mon Sep 17 00:00:00 2001 From: James Tang Date: Sun, 12 Apr 2015 23:55:10 +0800 Subject: [PATCH 033/113] v1.0.3 --- README.md | 4 +++- Spring.podspec | 2 +- 2 files changed, 4 insertions(+), 2 deletions(-) diff --git a/README.md b/README.md index 0db91ec..a8322e3 100644 --- a/README.md +++ b/README.md @@ -4,7 +4,7 @@ Drop in the Spring folder to your Xcode project. Or via CocoaPods: -`pod 'Spring', '~> 1.0.2'` +`pod 'Spring', '~> 1.0.3'` ## Usage with Storyboard In Identity Inspector, connect the UIView to SpringView Class and set the animation properties in Attribute Inspector. @@ -92,6 +92,8 @@ Animations won't autostart when view is reached via performSegueWithIdentifier. Animations using IBInspectables are currently not working in iOS 7. iOS 8 is supported. We're looking for a fix. Animations in code works for both iOS 7 and 8. +This project now requires Xcode 6.3 and Swift 1.2. For old version please download [1.0.2](https://github.com/MengTo/Spring/tree/1.0.2) + ## Tutorials - Tutorials available on [Design+Code](https://designcode.io/swiftapp). - [Integrate Spring to existing Objective-C projects](https://medium.com/ios-apprentice/using-swift-in-objective-c-projects-f7e7a09f8be) diff --git a/Spring.podspec b/Spring.podspec index 37b387a..a381019 100644 --- a/Spring.podspec +++ b/Spring.podspec @@ -1,6 +1,6 @@ Pod::Spec.new do |s| s.name = 'Spring' - s.version = '1.0.2' + s.version = '1.0.3' s.license = 'MIT' s.summary = 'A library to simplify iOS animations in Swift.' s.homepage = 'https://github.com/MengTo/Spring' From d3623430c59a0b8bf36f908a4ce284f641ce9375 Mon Sep 17 00:00:00 2001 From: Meng To Date: Mon, 8 Jun 2015 22:30:25 -0700 Subject: [PATCH 034/113] Fix for Swift 2 with some warnings - Couldn't find solution for timeAgoSinceDate - Has some warnings --- Spring/BlurView.swift | 4 +- Spring/DesignableLabel.swift | 8 +- Spring/DesignableTabBarController.swift | 12 +- Spring/DesignableTextField.swift | 8 +- Spring/DesignableTextView.swift | 8 +- Spring/ImageLoader.swift | 12 +- Spring/KeyboardLayoutConstraint.swift | 4 +- Spring/LoadingView.swift | 6 +- Spring/Misc.swift | 147 ++++++++++++------------ Spring/SoundPlayer.swift | 2 +- Spring/SpringAnimation.swift | 6 +- Spring/TransitionManager.swift | 6 +- Spring/TransitionZoom.swift | 6 +- SpringApp.xcodeproj/project.pbxproj | 1 + SpringApp/SpringViewController.swift | 4 +- 15 files changed, 120 insertions(+), 114 deletions(-) diff --git a/Spring/BlurView.swift b/Spring/BlurView.swift index 4583633..c512b98 100644 --- a/Spring/BlurView.swift +++ b/Spring/BlurView.swift @@ -25,8 +25,8 @@ import UIKit public func insertBlurView (view: UIView, style: UIBlurEffectStyle) { view.backgroundColor = UIColor.clearColor() - var blurEffect = UIBlurEffect(style: style) - var blurEffectView = UIVisualEffectView(effect: blurEffect) + let blurEffect = UIBlurEffect(style: style) + let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.frame = view.bounds view.insertSubview(blurEffectView, atIndex: 0) } \ No newline at end of file diff --git a/Spring/DesignableLabel.swift b/Spring/DesignableLabel.swift index e982cb4..146174b 100644 --- a/Spring/DesignableLabel.swift +++ b/Spring/DesignableLabel.swift @@ -26,13 +26,13 @@ import UIKit @IBInspectable public var lineHeight: CGFloat = 1.5 { didSet { - var font = UIFont(name: self.font.fontName, size: self.font.pointSize) - var text = self.text + let font = UIFont(name: self.font.fontName, size: self.font.pointSize) + let text = self.text - var paragraphStyle = NSMutableParagraphStyle() + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight - var attributedString = NSMutableAttributedString(string: text!) + let attributedString = NSMutableAttributedString(string: text!) attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(NSFontAttributeName, value: font!, range: NSMakeRange(0, attributedString.length)) diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index fc57f65..482d7ca 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] + var tabBarItems = self.tabBar.items as [UITabBarItem]! tabBarItems[0].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -56,7 +56,7 @@ import UIKit @IBInspectable var secondSelectedImage: UIImage? { didSet { if let image = secondSelectedImage { - var tabBarItems = self.tabBar.items as! [UITabBarItem] + var tabBarItems = self.tabBar.items as [UITabBarItem]! tabBarItems[1].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -65,7 +65,7 @@ import UIKit @IBInspectable var thirdSelectedImage: UIImage? { didSet { if let image = thirdSelectedImage { - var tabBarItems = self.tabBar.items as! [UITabBarItem] + var tabBarItems = self.tabBar.items as [UITabBarItem]! tabBarItems[2].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -74,7 +74,7 @@ import UIKit @IBInspectable var fourthSelectedImage: UIImage? { didSet { if let image = fourthSelectedImage { - var tabBarItems = self.tabBar.items as! [UITabBarItem] + var tabBarItems = self.tabBar.items as [UITabBarItem]! tabBarItems[3].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -83,7 +83,7 @@ import UIKit @IBInspectable var fifthSelectedImage: UIImage? { didSet { if let image = fifthSelectedImage { - var tabBarItems = self.tabBar.items as! [UITabBarItem] + var tabBarItems = self.tabBar.items as [UITabBarItem]! tabBarItems[4].selectedImage = image.imageWithRenderingMode(UIImageRenderingMode.AlwaysTemplate) } } @@ -92,7 +92,7 @@ import UIKit override func viewDidLoad() { super.viewDidLoad() - for item in self.tabBar.items as! [UITabBarItem] { + for item in self.tabBar.items as [UITabBarItem]! { if let image = item.image { item.image = image.imageWithColor(self.normalTint).imageWithRenderingMode(UIImageRenderingMode.AlwaysOriginal) } diff --git a/Spring/DesignableTextField.swift b/Spring/DesignableTextField.swift index 7d70e2b..4c2656e 100644 --- a/Spring/DesignableTextField.swift +++ b/Spring/DesignableTextField.swift @@ -34,7 +34,7 @@ import UIKit @IBInspectable public var sidePadding: CGFloat = 0 { didSet { - var padding = UIView(frame: CGRectMake(0, 0, sidePadding, sidePadding)) + let padding = UIView(frame: CGRectMake(0, 0, sidePadding, sidePadding)) leftViewMode = UITextFieldViewMode.Always leftView = padding @@ -46,7 +46,7 @@ import UIKit @IBInspectable public var leftPadding: CGFloat = 0 { didSet { - var padding = UIView(frame: CGRectMake(0, 0, leftPadding, 0)) + let padding = UIView(frame: CGRectMake(0, 0, leftPadding, 0)) leftViewMode = UITextFieldViewMode.Always leftView = padding @@ -55,7 +55,7 @@ import UIKit @IBInspectable public var rightPadding: CGFloat = 0 { didSet { - var padding = UIView(frame: CGRectMake(0, 0, 0, rightPadding)) + let padding = UIView(frame: CGRectMake(0, 0, 0, rightPadding)) rightViewMode = UITextFieldViewMode.Always rightView = padding @@ -82,7 +82,7 @@ import UIKit @IBInspectable public var lineHeight: CGFloat = 1.5 { didSet { - var font = UIFont(name: self.font.fontName, size: self.font.pointSize) + var font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) var text = self.text var paragraphStyle = NSMutableParagraphStyle() diff --git a/Spring/DesignableTextView.swift b/Spring/DesignableTextView.swift index cec69e6..27fe285 100644 --- a/Spring/DesignableTextView.swift +++ b/Spring/DesignableTextView.swift @@ -44,13 +44,13 @@ import UIKit @IBInspectable public var lineHeight: CGFloat = 1.5 { didSet { - var font = UIFont(name: self.font.fontName, size: self.font.pointSize) - var text = self.text + let font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) + let text = self.text - var paragraphStyle = NSMutableParagraphStyle() + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight - var attributedString = NSMutableAttributedString(string: text!) + let attributedString = NSMutableAttributedString(string: text!) attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(NSFontAttributeName, value: font!, range: NSMakeRange(0, attributedString.length)) diff --git a/Spring/ImageLoader.swift b/Spring/ImageLoader.swift index fe13699..cec5fd6 100755 --- a/Spring/ImageLoader.swift +++ b/Spring/ImageLoader.swift @@ -37,7 +37,7 @@ public class ImageLoader { public func imageForUrl(urlString: String, completionHandler:(image: UIImage?, url: String) -> ()) { dispatch_async(dispatch_get_global_queue(DISPATCH_QUEUE_PRIORITY_BACKGROUND, 0), {()in - var data: NSData? = self.cache.objectForKey(urlString) as? NSData + let data: NSData? = self.cache.objectForKey(urlString) as? NSData if let goodData = data { let image = UIImage(data: goodData) @@ -47,23 +47,23 @@ public class ImageLoader { return } - var downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: {(data: NSData!, response: NSURLResponse!, error: NSError!) -> Void in + let downloadTask: NSURLSessionTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in if (error != nil) { completionHandler(image: nil, url: urlString) return } if data != nil { - let image = UIImage(data: data) - self.cache.setObject(data, forKey: urlString) + let image = UIImage(data: data!) + self.cache.setObject(data!, forKey: urlString) dispatch_async(dispatch_get_main_queue(), {() in completionHandler(image: image, url: urlString) }) return } - - }) + })! downloadTask.resume() + }) } diff --git a/Spring/KeyboardLayoutConstraint.swift b/Spring/KeyboardLayoutConstraint.swift index b8dfe5e..1fad0b5 100644 --- a/Spring/KeyboardLayoutConstraint.swift +++ b/Spring/KeyboardLayoutConstraint.swift @@ -53,7 +53,7 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { case let (.Some(duration), .Some(curve)): - let options = UIViewAnimationOptions(curve.unsignedLongValue) + let options = UIViewAnimationOptions(rawValue: curve.unsignedLongValue) UIView.animateWithDuration( NSTimeInterval(duration.doubleValue), @@ -82,7 +82,7 @@ public class KeyboardLayoutConstraint: NSLayoutConstraint { switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { case let (.Some(duration), .Some(curve)): - let options = UIViewAnimationOptions(curve.unsignedLongValue) + let options = UIViewAnimationOptions(rawValue: curve.unsignedLongValue) UIView.animateWithDuration( NSTimeInterval(duration.doubleValue), diff --git a/Spring/LoadingView.swift b/Spring/LoadingView.swift index 8884037..a763140 100644 --- a/Spring/LoadingView.swift +++ b/Spring/LoadingView.swift @@ -60,7 +60,7 @@ public extension UIView { self.addSubview(loadingXibView) loadingXibView.alpha = 0 - spring(0.7, { + spring(0.7, animations: { loadingXibView.alpha = 1 }) } @@ -70,10 +70,10 @@ public extension UIView { if let loadingXibView = self.viewWithTag(LoadingViewConstants.Tag) { loadingXibView.alpha = 1 - springWithCompletion(0.7, { + springWithCompletion(0.7, animations: { loadingXibView.alpha = 0 loadingXibView.transform = CGAffineTransformMakeScale(3, 3) - }, { (completed) -> Void in + }, completion: { (completed) -> Void in loadingXibView.removeFromSuperview() }) } diff --git a/Spring/Misc.swift b/Spring/Misc.swift index b537590..84211d7 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -23,7 +23,7 @@ import UIKit public extension String { - public var length: Int { return count(self) } + public var length: Int { return self.characters.count } public func toURL() -> NSURL? { return NSURL(string: self) @@ -32,7 +32,12 @@ public extension String { public func htmlToAttributedString(text: String) -> NSAttributedString! { let htmlData = text.dataUsingEncoding(NSUTF8StringEncoding, allowLossyConversion: false) - let htmlString = NSAttributedString(data: htmlData!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil, error: nil) + let htmlString: NSAttributedString? + do { + htmlString = try NSAttributedString(data: htmlData!, options: [NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType], documentAttributes: nil) + } catch _ { + htmlString = nil + } return htmlString } @@ -72,7 +77,7 @@ public extension UIColor { let scanner = NSScanner(string: hex) var hexValue: CUnsignedLongLong = 0 if scanner.scanHexLongLong(&hexValue) { - switch (count(hex)) { + switch (hex.characters.count) { case 3: red = CGFloat((hexValue & 0xF00) >> 8) / 15.0 green = CGFloat((hexValue & 0x0F0) >> 4) / 15.0 @@ -92,10 +97,10 @@ public extension UIColor { blue = CGFloat((hexValue & 0x0000FF00) >> 8) / 255.0 alpha = CGFloat(hexValue & 0x000000FF) / 255.0 default: - print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8") + print("Invalid RGB string, number of characters after '#' should be either 3, 4, 6 or 8", appendNewline: false) } } else { - println("Scan hex error") + print("Scan hex error") } self.init(red:red, green:green, blue:blue, alpha:alpha) } @@ -135,77 +140,77 @@ public func randomStringWithLength (len : Int) -> NSString { let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - var randomString : NSMutableString = NSMutableString(capacity: len) + let randomString : NSMutableString = NSMutableString(capacity: len) for (var i=0; i < len; i++){ - var length = UInt32 (letters.length) - var rand = arc4random_uniform(length) + let length = UInt32 (letters.length) + let rand = arc4random_uniform(length) randomString.appendFormat("%C", letters.characterAtIndex(Int(rand))) } return randomString } -public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { - let calendar = NSCalendar.currentCalendar() - let unitFlags = NSCalendarUnit.CalendarUnitMinute | NSCalendarUnit.CalendarUnitHour | NSCalendarUnit.CalendarUnitDay | NSCalendarUnit.CalendarUnitWeekOfYear | NSCalendarUnit.CalendarUnitMonth | NSCalendarUnit.CalendarUnitYear | NSCalendarUnit.CalendarUnitSecond - let now = NSDate() - let earliest = now.earlierDate(date) - let latest = now.laterDate(date) - let components:NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: nil) - - if (components.year >= 2) { - return "\(components.year)y" - } else if (components.year >= 1){ - if (numericDates){ - return "1y" - } else { - return "1y" - } - } else if (components.month >= 2) { - return "\(components.month * 4)w" - } else if (components.month >= 1){ - if (numericDates){ - return "4w" - } else { - return "4w" - } - } else if (components.weekOfYear >= 2) { - return "\(components.weekOfYear)w" - } else if (components.weekOfYear >= 1){ - if (numericDates){ - return "1w" - } else { - return "1w" - } - } else if (components.day >= 2) { - return "\(components.day)d" - } else if (components.day >= 1){ - if (numericDates){ - return "1d" - } else { - return "1d" - } - } else if (components.hour >= 2) { - return "\(components.hour)h" - } else if (components.hour >= 1){ - if (numericDates){ - return "1h" - } else { - return "1h" - } - } else if (components.minute >= 2) { - return "\(components.minute)m" - } else if (components.minute >= 1){ - if (numericDates){ - return "1m" - } else { - return "1m" - } - } else if (components.second >= 3) { - return "\(components.second)s" - } else { - return "now" - } - -} \ No newline at end of file +//public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { +// let calendar = NSCalendar.currentCalendar() +// let unitFlags: NSCalendarUnit = [NSCalendarUnit.Minute, NSCalendarUnit.Hour, NSCalendarUnit.Day, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Month, NSCalendarUnit.Year, NSCalendarUnit.Second] +// let now = NSDate() +// let earliest = now.earlierDate(date) +// let latest = (earliest == now) ? date : now +// let components:NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: nil) +// +// if (components.year >= 2) { +// return "\(components.year)y" +// } else if (components.year >= 1){ +// if (numericDates){ +// return "1y" +// } else { +// return "1y" +// } +// } else if (components.month >= 2) { +// return "\(components.month * 4)w" +// } else if (components.month >= 1){ +// if (numericDates){ +// return "4w" +// } else { +// return "4w" +// } +// } else if (components.weekOfYear >= 2) { +// return "\(components.weekOfYear)w" +// } else if (components.weekOfYear >= 1){ +// if (numericDates){ +// return "1w" +// } else { +// return "1w" +// } +// } else if (components.day >= 2) { +// return "\(components.day)d" +// } else if (components.day >= 1){ +// if (numericDates){ +// return "1d" +// } else { +// return "1d" +// } +// } else if (components.hour >= 2) { +// return "\(components.hour)h" +// } else if (components.hour >= 1){ +// if (numericDates){ +// return "1h" +// } else { +// return "1h" +// } +// } else if (components.minute >= 2) { +// return "\(components.minute)m" +// } else if (components.minute >= 1){ +// if (numericDates){ +// return "1m" +// } else { +// return "1m" +// } +// } else if (components.second >= 3) { +// return "\(components.second)s" +// } else { +// return "now" +// } +// +//} \ No newline at end of file diff --git a/Spring/SoundPlayer.swift b/Spring/SoundPlayer.swift index d39830c..11b595a 100644 --- a/Spring/SoundPlayer.swift +++ b/Spring/SoundPlayer.swift @@ -50,7 +50,7 @@ public class SoundPlayer: NSObject { AudioServicesPlaySystemSound(soundID) } else { - println("Could not find sound file name `\(soundFile)`") + print("Could not find sound file name `\(soundFile)`") } } diff --git a/Spring/SpringAnimation.swift b/Spring/SpringAnimation.swift index ff5d787..4534317 100644 --- a/Spring/SpringAnimation.swift +++ b/Spring/SpringAnimation.swift @@ -29,7 +29,7 @@ public func spring(duration: NSTimeInterval, animations: (() -> Void)!) { delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, - options: nil, + options: [], animations: { animations() @@ -100,7 +100,7 @@ public func springWithDelay(duration: NSTimeInterval, delay: NSTimeInterval, ani delay: delay, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, - options: nil, + options: [], animations: { animations() @@ -116,7 +116,7 @@ public func springWithCompletion(duration: NSTimeInterval, animations: (() -> Vo delay: 0, usingSpringWithDamping: 0.7, initialSpringVelocity: 0.7, - options: nil, + options: [], animations: { animations() diff --git a/Spring/TransitionManager.swift b/Spring/TransitionManager.swift index 401e1c3..0c9608a 100644 --- a/Spring/TransitionManager.swift +++ b/Spring/TransitionManager.swift @@ -28,7 +28,7 @@ public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, var duration = 0.3 public func animateTransition(transitionContext: UIViewControllerContextTransitioning) { - let container = transitionContext.containerView() + let container = transitionContext.containerView()! let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! @@ -65,12 +65,12 @@ public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, } } - delay(duration, { + delay(duration, closure: { transitionContext.completeTransition(true) }) } - public func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { + public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { return duration } diff --git a/Spring/TransitionZoom.swift b/Spring/TransitionZoom.swift index da1f4bc..3b5112b 100644 --- a/Spring/TransitionZoom.swift +++ b/Spring/TransitionZoom.swift @@ -28,7 +28,7 @@ public class TransitionZoom: NSObject, UIViewControllerTransitioningDelegate, UI var duration = 0.4 public func animateTransition(transitionContext: UIViewControllerContextTransitioning) { - let container = transitionContext.containerView() + let container = transitionContext.containerView()! let fromView = transitionContext.viewForKey(UITransitionContextFromViewKey)! let toView = transitionContext.viewForKey(UITransitionContextToViewKey)! @@ -57,12 +57,12 @@ public class TransitionZoom: NSObject, UIViewControllerTransitioningDelegate, UI } } - delay(duration, { + delay(duration, closure: { transitionContext.completeTransition(true) }) } - public func transitionDuration(transitionContext: UIViewControllerContextTransitioning) -> NSTimeInterval { + public func transitionDuration(transitionContext: UIViewControllerContextTransitioning?) -> NSTimeInterval { return duration } diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index a16045e..f0b4814 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -407,6 +407,7 @@ 964117331A5BE90A000E3A5A /* Project object */ = { isa = PBXProject; attributes = { + LastSwiftUpdateCheck = 0700; LastUpgradeCheck = 0620; ORGANIZATIONNAME = "Meng To"; TargetAttributes = { diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index a401517..bfa4c85 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -103,14 +103,14 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView } func minimizeView(sender: AnyObject) { - spring(0.7, { + spring(0.7, animations: { self.view.transform = CGAffineTransformMakeScale(0.935, 0.935) }) UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.LightContent, animated: true) } func maximizeView(sender: AnyObject) { - spring(0.7, { + spring(0.7, animations: { self.view.transform = CGAffineTransformMakeScale(1, 1) }) UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.Default, animated: true) From b42692af30c6fc58048e992359d229cd90e8a068 Mon Sep 17 00:00:00 2001 From: Meng To Date: Mon, 8 Jun 2015 23:11:17 -0700 Subject: [PATCH 035/113] Fixed warnings, timeAgo still not working --- Spring/DesignableTextField.swift | 8 ++++---- Spring/LoadingView.swift | 2 +- SpringApp/SpringViewController.swift | 2 +- 3 files changed, 6 insertions(+), 6 deletions(-) diff --git a/Spring/DesignableTextField.swift b/Spring/DesignableTextField.swift index 4c2656e..6b83572 100644 --- a/Spring/DesignableTextField.swift +++ b/Spring/DesignableTextField.swift @@ -82,13 +82,13 @@ import UIKit @IBInspectable public var lineHeight: CGFloat = 1.5 { didSet { - var font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) - var text = self.text + let font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) + let text = self.text - var paragraphStyle = NSMutableParagraphStyle() + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight - var attributedString = NSMutableAttributedString(string: text!) + let attributedString = NSMutableAttributedString(string: text!) attributedString.addAttribute(NSParagraphStyleAttributeName, value: paragraphStyle, range: NSMakeRange(0, attributedString.length)) attributedString.addAttribute(NSFontAttributeName, value: font!, range: NSMakeRange(0, attributedString.length)) diff --git a/Spring/LoadingView.swift b/Spring/LoadingView.swift index a763140..4edb051 100644 --- a/Spring/LoadingView.swift +++ b/Spring/LoadingView.swift @@ -49,7 +49,7 @@ public extension UIView { public func showLoading() { - if let loadingXibView = self.viewWithTag(LoadingViewConstants.Tag) { + if self.viewWithTag(LoadingViewConstants.Tag) != nil { // If loading view is already found in current view hierachy, do nothing return } diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index bfa4c85..108822e 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -213,7 +213,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView return data[component].count } - func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { + func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String? { return data[component][row] } From a61304a43cd760f678e563c78b50458b1e6320b2 Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 9 Jun 2015 10:58:12 -0700 Subject: [PATCH 036/113] Fix for Swift 2 --- Spring/ImageLoader.swift | 2 +- Spring/Misc.swift | 126 +++++++++++++++++++-------------------- 2 files changed, 64 insertions(+), 64 deletions(-) diff --git a/Spring/ImageLoader.swift b/Spring/ImageLoader.swift index cec5fd6..42645e0 100755 --- a/Spring/ImageLoader.swift +++ b/Spring/ImageLoader.swift @@ -47,7 +47,7 @@ public class ImageLoader { return } - let downloadTask: NSURLSessionTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in + let downloadTask: NSURLSessionDataTask = NSURLSession.sharedSession().dataTaskWithURL(NSURL(string: urlString)!, completionHandler: { (data, response, error) -> Void in if (error != nil) { completionHandler(image: nil, url: urlString) return diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 84211d7..055e402 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -151,66 +151,66 @@ public func randomStringWithLength (len : Int) -> NSString { return randomString } -//public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { -// let calendar = NSCalendar.currentCalendar() -// let unitFlags: NSCalendarUnit = [NSCalendarUnit.Minute, NSCalendarUnit.Hour, NSCalendarUnit.Day, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Month, NSCalendarUnit.Year, NSCalendarUnit.Second] -// let now = NSDate() -// let earliest = now.earlierDate(date) -// let latest = (earliest == now) ? date : now -// let components:NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: nil) -// -// if (components.year >= 2) { -// return "\(components.year)y" -// } else if (components.year >= 1){ -// if (numericDates){ -// return "1y" -// } else { -// return "1y" -// } -// } else if (components.month >= 2) { -// return "\(components.month * 4)w" -// } else if (components.month >= 1){ -// if (numericDates){ -// return "4w" -// } else { -// return "4w" -// } -// } else if (components.weekOfYear >= 2) { -// return "\(components.weekOfYear)w" -// } else if (components.weekOfYear >= 1){ -// if (numericDates){ -// return "1w" -// } else { -// return "1w" -// } -// } else if (components.day >= 2) { -// return "\(components.day)d" -// } else if (components.day >= 1){ -// if (numericDates){ -// return "1d" -// } else { -// return "1d" -// } -// } else if (components.hour >= 2) { -// return "\(components.hour)h" -// } else if (components.hour >= 1){ -// if (numericDates){ -// return "1h" -// } else { -// return "1h" -// } -// } else if (components.minute >= 2) { -// return "\(components.minute)m" -// } else if (components.minute >= 1){ -// if (numericDates){ -// return "1m" -// } else { -// return "1m" -// } -// } else if (components.second >= 3) { -// return "\(components.second)s" -// } else { -// return "now" -// } -// -//} \ No newline at end of file +public func timeAgoSinceDate(date:NSDate, numericDates:Bool) -> String { + let calendar = NSCalendar.currentCalendar() + let unitFlags: NSCalendarUnit = [NSCalendarUnit.Minute, NSCalendarUnit.Hour, NSCalendarUnit.Day, NSCalendarUnit.WeekOfYear, NSCalendarUnit.Month, NSCalendarUnit.Year, NSCalendarUnit.Second] + let now = NSDate() + let earliest = now.earlierDate(date) + let latest = (earliest == now) ? date : now + let components: NSDateComponents = calendar.components(unitFlags, fromDate: earliest, toDate: latest, options: []) + + if (components.year >= 2) { + return "\(components.year)y" + } else if (components.year >= 1){ + if (numericDates){ + return "1y" + } else { + return "1y" + } + } else if (components.month >= 2) { + return "\(components.month * 4)w" + } else if (components.month >= 1){ + if (numericDates){ + return "4w" + } else { + return "4w" + } + } else if (components.weekOfYear >= 2) { + return "\(components.weekOfYear)w" + } else if (components.weekOfYear >= 1){ + if (numericDates){ + return "1w" + } else { + return "1w" + } + } else if (components.day >= 2) { + return "\(components.day)d" + } else if (components.day >= 1){ + if (numericDates){ + return "1d" + } else { + return "1d" + } + } else if (components.hour >= 2) { + return "\(components.hour)h" + } else if (components.hour >= 1){ + if (numericDates){ + return "1h" + } else { + return "1h" + } + } else if (components.minute >= 2) { + return "\(components.minute)m" + } else if (components.minute >= 1){ + if (numericDates){ + return "1m" + } else { + return "1m" + } + } else if (components.second >= 3) { + return "\(components.second)s" + } else { + return "now" + } + +} \ No newline at end of file From 3f6d324b937ea4cf0f0dad1e00ae050d1fd49ab9 Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 9 Jun 2015 11:03:04 -0700 Subject: [PATCH 037/113] Update README.md --- README.md | 3 +++ 1 file changed, 3 insertions(+) diff --git a/README.md b/README.md index a8322e3..2506c71 100644 --- a/README.md +++ b/README.md @@ -1,5 +1,8 @@ ![](http://cl.ly/image/3a1r1d3l3D1j/spring-logo.jpg) +## Updated for Swift 2 +This update will be in this branch until Swift 2 is out of beta. + ## Installation Drop in the Spring folder to your Xcode project. From c257a69b0dea35757ef8f966497a367f034ce036 Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 9 Jun 2015 11:19:57 -0700 Subject: [PATCH 038/113] Update README.md --- README.md | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/README.md b/README.md index 2506c71..1d0023b 100644 --- a/README.md +++ b/README.md @@ -1,4 +1,4 @@ -![](http://cl.ly/image/3a1r1d3l3D1j/spring-logo.jpg) +![](http://cl.ly/image/012R0D3R3x2g/download/springswift2.jpg) ## Updated for Swift 2 This update will be in this branch until Swift 2 is out of beta. From dea15459d3fdaf5f37ae8f57073e14050d73b772 Mon Sep 17 00:00:00 2001 From: James Tang Date: Mon, 15 Jun 2015 01:00:16 +0800 Subject: [PATCH 039/113] Update README.md --- README.md | 6 +++++- 1 file changed, 5 insertions(+), 1 deletion(-) diff --git a/README.md b/README.md index 1d0023b..7daf4d6 100644 --- a/README.md +++ b/README.md @@ -7,7 +7,11 @@ This update will be in this branch until Swift 2 is out of beta. Drop in the Spring folder to your Xcode project. Or via CocoaPods: -`pod 'Spring', '~> 1.0.3'` +``` +use_frameworks! +pod 'Spring', :git => 'https://github.com/MengTo/Spring.git', :branch => 'swift2' +``` + ## Usage with Storyboard In Identity Inspector, connect the UIView to SpringView Class and set the animation properties in Attribute Inspector. From b4a3589aaa59bed5fc046f1940974d0ed69bdf99 Mon Sep 17 00:00:00 2001 From: Brandon Minch Date: Wed, 24 Jun 2015 15:01:49 -0600 Subject: [PATCH 040/113] Fix right padding on DesignableTextField --- Spring/DesignableTextField.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spring/DesignableTextField.swift b/Spring/DesignableTextField.swift index 7d70e2b..6a841c3 100644 --- a/Spring/DesignableTextField.swift +++ b/Spring/DesignableTextField.swift @@ -55,7 +55,7 @@ import UIKit @IBInspectable public var rightPadding: CGFloat = 0 { didSet { - var padding = UIView(frame: CGRectMake(0, 0, 0, rightPadding)) + var padding = UIView(frame: CGRectMake(0, 0, rightPadding, 0)) rightViewMode = UITextFieldViewMode.Always rightView = padding From 50b0b08f3f1c2c7b85101028c13ab1d1dac6dc9d Mon Sep 17 00:00:00 2001 From: Jaison Vieira Date: Sun, 28 Jun 2015 04:51:47 -0300 Subject: [PATCH 041/113] Make AutoTextView class public Now it can be used by importing Spring (with CocoaPods). --- Spring/AutoTextView.swift | 4 ++-- 1 file changed, 2 insertions(+), 2 deletions(-) diff --git a/Spring/AutoTextView.swift b/Spring/AutoTextView.swift index e1b3e31..3abced4 100644 --- a/Spring/AutoTextView.swift +++ b/Spring/AutoTextView.swift @@ -8,8 +8,8 @@ import UIKit -class AutoTextView: UITextView { - override func intrinsicContentSize() -> CGSize { +public class AutoTextView: UITextView { + override public func intrinsicContentSize() -> CGSize { var size = self.sizeThatFits(CGSizeMake(self.frame.size.width, CGFloat.max)) size.width = self.frame.size.width if text.length == 0 { From 8cfcdb2ae36f0a10f463f11cf813ffff52b8af82 Mon Sep 17 00:00:00 2001 From: Meng To Date: Tue, 30 Jun 2015 22:03:07 -0400 Subject: [PATCH 042/113] Update for Xcode 7 beta 2 --- Spring/DesignableTabBarController.swift | 2 +- Spring/Info.plist | 2 +- SpringApp.xcodeproj/project.pbxproj | 11 ++++++++++- .../xcshareddata/xcschemes/Spring.xcscheme | 5 ++++- .../xcshareddata/xcschemes/SpringApp.xcscheme | 5 ++++- SpringApp/Info.plist | 6 +++--- SpringAppTests/Info.plist | 2 +- SpringTests/Info.plist | 2 +- 8 files changed, 25 insertions(+), 10 deletions(-) diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index 482d7ca..3dea373 100644 --- a/Spring/DesignableTabBarController.swift +++ b/Spring/DesignableTabBarController.swift @@ -107,7 +107,7 @@ extension UIImage { let context = UIGraphicsGetCurrentContext() as CGContextRef CGContextTranslateCTM(context, 0, self.size.height) CGContextScaleCTM(context, 1.0, -1.0); - CGContextSetBlendMode(context, kCGBlendModeNormal) + CGContextSetBlendMode(context, CGBlendMode.Normal) let rect = CGRectMake(0, 0, self.size.width, self.size.height) as CGRect CGContextClipToMask(context, rect, self.CGImage) diff --git a/Spring/Info.plist b/Spring/Info.plist index bd4db03..d3de8ee 100644 --- a/Spring/Info.plist +++ b/Spring/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - designcode.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index f0b4814..3bc52d5 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -408,7 +408,7 @@ isa = PBXProject; attributes = { LastSwiftUpdateCheck = 0700; - LastUpgradeCheck = 0620; + LastUpgradeCheck = 0700; ORGANIZATIONNAME = "Meng To"; TargetAttributes = { 1A4FDA321A6E44780099D309 = { @@ -607,6 +607,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -627,6 +628,7 @@ INSTALL_PATH = "$(LOCAL_LIBRARY_DIR)/Frameworks"; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; SKIP_INSTALL = YES; TARGETED_DEVICE_FAMILY = "1,2"; @@ -649,6 +651,7 @@ 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)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; }; @@ -664,6 +667,7 @@ 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)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; }; @@ -689,6 +693,7 @@ "CODE_SIGN_IDENTITY[sdk=iphoneos*]" = "iPhone Developer"; COPY_PHASE_STRIP = NO; ENABLE_STRICT_OBJC_MSGSEND = YES; + ENABLE_TESTABILITY = YES; GCC_C_LANGUAGE_STANDARD = gnu99; GCC_DYNAMIC_NO_PIC = NO; GCC_OPTIMIZATION_LEVEL = 0; @@ -753,6 +758,7 @@ INFOPLIST_FILE = SpringApp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -765,6 +771,7 @@ INFOPLIST_FILE = SpringApp/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.0; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks"; + PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; PRODUCT_NAME = "$(TARGET_NAME)"; TARGETED_DEVICE_FAMILY = "1,2"; }; @@ -784,6 +791,7 @@ ); 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)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; }; @@ -799,6 +807,7 @@ ); 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)"; TEST_HOST = "$(BUILT_PRODUCTS_DIR)/SpringApp.app/SpringApp"; }; diff --git a/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme index 492fc4d..8066cbf 100644 --- a/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme +++ b/SpringApp.xcodeproj/xcshareddata/xcschemes/Spring.xcscheme @@ -1,6 +1,6 @@ + + + + diff --git a/SpringApp/Info.plist b/SpringApp/Info.plist index f5b3473..01aa7f4 100644 --- a/SpringApp/Info.plist +++ b/SpringApp/Info.plist @@ -2,14 +2,12 @@ - UIViewControllerBasedStatusBarAppearance - CFBundleDevelopmentRegion en CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - designcode.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName @@ -38,5 +36,7 @@ UIInterfaceOrientationLandscapeLeft UIInterfaceOrientationLandscapeRight + UIViewControllerBasedStatusBarAppearance + diff --git a/SpringAppTests/Info.plist b/SpringAppTests/Info.plist index b1fb88b..ba72822 100644 --- a/SpringAppTests/Info.plist +++ b/SpringAppTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - designcode.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName diff --git a/SpringTests/Info.plist b/SpringTests/Info.plist index 609467f..ba72822 100644 --- a/SpringTests/Info.plist +++ b/SpringTests/Info.plist @@ -7,7 +7,7 @@ CFBundleExecutable $(EXECUTABLE_NAME) CFBundleIdentifier - com.jamztang.$(PRODUCT_NAME:rfc1034identifier) + $(PRODUCT_BUNDLE_IDENTIFIER) CFBundleInfoDictionaryVersion 6.0 CFBundleName From 2446b6580d6e46930a9f37b46e03ea980b63f412 Mon Sep 17 00:00:00 2001 From: Chen Wei Date: Thu, 9 Jul 2015 12:23:34 +0800 Subject: [PATCH 043/113] async image to placeholder when it is nil --- Spring/AsyncImageView.swift | 2 +- 1 file changed, 1 insertion(+), 1 deletion(-) diff --git a/Spring/AsyncImageView.swift b/Spring/AsyncImageView.swift index 0e20cdf..f3ac178 100644 --- a/Spring/AsyncImageView.swift +++ b/Spring/AsyncImageView.swift @@ -34,7 +34,7 @@ public class AsyncImageView: UIImageView { if let strongSelf = self { dispatch_async(dispatch_get_main_queue(), { () -> Void in if strongSelf.url?.absoluteString == url { - strongSelf.image = image + strongSelf.image = image ?? strongSelf.placeholderImage } }) } From 3f9febe52ba261f34a864ad1eaffa30d6e9442b9 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 12:56:05 +0200 Subject: [PATCH 044/113] Add AnimationPreset enumeration. --- Spring/Spring.swift | 30 ++++++++++++++++++++++++++++++ 1 file changed, 30 insertions(+) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index d1750fa..3b7d2c5 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -102,6 +102,36 @@ public class Spring : NSObject { private var transform : CGAffineTransform { get { return view.transform } set { view.transform = newValue }} private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } + 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" + } + func animatePreset() { alpha = 0.99 if animation == "" { From ff9b9949ec3c5979e814cc1b5dd7f0cfe859c7dc Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 13:17:21 +0200 Subject: [PATCH 045/113] Use enum in switch statement. --- Spring/Spring.swift | 395 ++++++++++++++++++++++---------------------- 1 file changed, 195 insertions(+), 200 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 3b7d2c5..92312fc 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -134,209 +134,204 @@ public class Spring : NSObject { func animatePreset() { alpha = 0.99 - if animation == "" { - return - } - - switch animation { - case "slideLeft": - x = 300*force - case "slideRight": - x = -300*force - case "slideDown": - y = -300*force - case "slideUp": - y = 300*force - case "squeezeLeft": - x = 300 - scaleX = 3*force - case "squeezeRight": - x = -300 - scaleX = 3*force - case "squeezeDown": - y = -300 - scaleY = 3*force - case "squeezeUp": - y = 300 - scaleY = 3*force - case "fadeIn": - opacity = 0 - case "fadeOut": - animateFrom = false - opacity = 0 - case "fadeOutIn": - let animation = CABasicAnimation() - animation.keyPath = "opacity" - animation.fromValue = 1 - animation.toValue = 0 - animation.timingFunction = getTimingFunction(curve) - animation.duration = CFTimeInterval(duration) - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - animation.autoreverses = true - layer.addAnimation(animation, forKey: "fade") - case "fadeInLeft": - opacity = 0 - x = 300*force - case "fadeInRight": - x = -300*force - opacity = 0 - case "fadeInDown": - y = -300*force - opacity = 0 - case "fadeInUp": - y = 300*force - opacity = 0 - case "zoomIn": - opacity = 0 - scaleX = 2*force - scaleY = 2*force - case "zoomOut": - animateFrom = false - opacity = 0 - scaleX = 2*force - scaleY = 2*force - case "fall": - animateFrom = false - rotate = 15 * CGFloat(M_PI/180) - y = 600*force - case "shake": - let animation = CAKeyframeAnimation() - animation.keyPath = "position.x" - animation.values = [0, 30*force, -30*force, 30*force, 0] - animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - animation.timingFunction = getTimingFunction(curve) - animation.duration = CFTimeInterval(duration) - animation.additive = true - animation.repeatCount = repeatCount - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(animation, forKey: "shake") - case "pop": - let animation = CAKeyframeAnimation() - animation.keyPath = "transform.scale" - animation.values = [0, 0.2*force, -0.2*force, 0.2*force, 0] - animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - animation.timingFunction = getTimingFunction(curve) - animation.duration = CFTimeInterval(duration) - animation.additive = true - animation.repeatCount = repeatCount - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(animation, forKey: "pop") - case "flipX": - rotate = 0 - scaleX = 1 - scaleY = 1 - var perspective = CATransform3DIdentity - perspective.m34 = -1.0 / layer.frame.size.width/2 - - let animation = CABasicAnimation() - animation.keyPath = "transform" - animation.fromValue = NSValue(CATransform3D: - CATransform3DMakeRotation(0, 0, 0, 0)) - animation.toValue = NSValue(CATransform3D: - CATransform3DConcat(perspective, CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0))) - animation.duration = CFTimeInterval(duration) - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - animation.timingFunction = getTimingFunction(curve) - layer.addAnimation(animation, forKey: "3d") - case "flipY": - var perspective = CATransform3DIdentity - perspective.m34 = -1.0 / layer.frame.size.width/2 - - let animation = CABasicAnimation() - animation.keyPath = "transform" - animation.fromValue = NSValue(CATransform3D: - CATransform3DMakeRotation(0, 0, 0, 0)) - animation.toValue = NSValue(CATransform3D: - CATransform3DConcat(perspective,CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0))) - animation.duration = CFTimeInterval(duration) - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - animation.timingFunction = getTimingFunction(curve) - layer.addAnimation(animation, forKey: "3d") - case "morph": - let morphX = CAKeyframeAnimation() - morphX.keyPath = "transform.scale.x" - morphX.values = [1, 1.3*force, 0.7, 1.3*force, 1] - morphX.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - morphX.timingFunction = getTimingFunction(curve) - morphX.duration = CFTimeInterval(duration) - morphX.repeatCount = repeatCount - morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(morphX, forKey: "morphX") - - let morphY = CAKeyframeAnimation() - morphY.keyPath = "transform.scale.y" - morphY.values = [1, 0.7, 1.3*force, 0.7, 1] - morphY.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - morphY.timingFunction = getTimingFunction(curve) - morphY.duration = CFTimeInterval(duration) - morphY.repeatCount = repeatCount - morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(morphY, forKey: "morphY") - case "squeeze": - let morphX = CAKeyframeAnimation() - morphX.keyPath = "transform.scale.x" - morphX.values = [1, 1.5*force, 0.5, 1.5*force, 1] - morphX.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - morphX.timingFunction = getTimingFunction(curve) - morphX.duration = CFTimeInterval(duration) - morphX.repeatCount = repeatCount - morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(morphX, forKey: "morphX") - - let morphY = CAKeyframeAnimation() - morphY.keyPath = "transform.scale.y" - morphY.values = [1, 0.5, 1, 0.5, 1] - morphY.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - morphY.timingFunction = getTimingFunction(curve) - morphY.duration = CFTimeInterval(duration) - morphY.repeatCount = repeatCount - morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(morphY, forKey: "morphY") - case "flash": - let animation = CABasicAnimation() - animation.keyPath = "opacity" - animation.fromValue = 1 - animation.toValue = 0 - animation.duration = CFTimeInterval(duration) - animation.repeatCount = repeatCount * 2.0 - animation.autoreverses = true - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(animation, forKey: "flash") - case "wobble": - let animation = CAKeyframeAnimation() - animation.keyPath = "transform.rotation" - animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] - animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - animation.duration = CFTimeInterval(duration) - animation.additive = true - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(animation, forKey: "wobble") - - let x = CAKeyframeAnimation() - x.keyPath = "position.x" - x.values = [0, 30*force, -30*force, 30*force, 0] - x.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - x.timingFunction = getTimingFunction(curve) - x.duration = CFTimeInterval(duration) - x.additive = true - x.repeatCount = repeatCount - x.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(x, forKey: "x") - case "swing": - let animation = CAKeyframeAnimation() - animation.keyPath = "transform.rotation" - animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] - animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] - animation.duration = CFTimeInterval(duration) - animation.additive = true - animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) - layer.addAnimation(animation, forKey: "swing") - default: - x = 300 + if let animation = AnimationPreset(rawValue: animation) { + switch animation { + case .SlideLeft: + x = 300*force + case .SlideRight: + x = -300*force + case .SlideDown: + y = -300*force + case .SlideUp: + y = 300*force + case .SqueezeLeft: + x = 300 + scaleX = 3*force + case .SqueezeRight: + x = -300 + scaleX = 3*force + case .SqueezeDown: + y = -300 + scaleY = 3*force + case .SqueezeUp: + y = 300 + scaleY = 3*force + case .FadeIn: + opacity = 0 + case .FadeOut: + animateFrom = false + opacity = 0 + case .FadeOutIn: + let animation = CABasicAnimation() + animation.keyPath = "opacity" + animation.fromValue = 1 + animation.toValue = 0 + animation.timingFunction = getTimingFunction(curve) + animation.duration = CFTimeInterval(duration) + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + animation.autoreverses = true + layer.addAnimation(animation, forKey: "fade") + case .FadeInLeft: + opacity = 0 + x = 300*force + case .FadeInRight: + x = -300*force + opacity = 0 + case .FadeInDown: + y = -300*force + opacity = 0 + case .FadeInUp: + y = 300*force + opacity = 0 + case .ZoomIn: + opacity = 0 + scaleX = 2*force + scaleY = 2*force + case .ZoomOut: + animateFrom = false + opacity = 0 + scaleX = 2*force + scaleY = 2*force + case .Fall: + animateFrom = false + rotate = 15 * CGFloat(M_PI/180) + y = 600*force + case .Shake: + let animation = CAKeyframeAnimation() + animation.keyPath = "position.x" + animation.values = [0, 30*force, -30*force, 30*force, 0] + animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + animation.timingFunction = getTimingFunction(curve) + animation.duration = CFTimeInterval(duration) + animation.additive = true + animation.repeatCount = repeatCount + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(animation, forKey: "shake") + case .Pop: + let animation = CAKeyframeAnimation() + animation.keyPath = "transform.scale" + animation.values = [0, 0.2*force, -0.2*force, 0.2*force, 0] + animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + animation.timingFunction = getTimingFunction(curve) + animation.duration = CFTimeInterval(duration) + animation.additive = true + animation.repeatCount = repeatCount + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(animation, forKey: "pop") + case .FlipX: + rotate = 0 + scaleX = 1 + scaleY = 1 + var perspective = CATransform3DIdentity + perspective.m34 = -1.0 / layer.frame.size.width/2 + + let animation = CABasicAnimation() + animation.keyPath = "transform" + animation.fromValue = NSValue(CATransform3D: + CATransform3DMakeRotation(0, 0, 0, 0)) + animation.toValue = NSValue(CATransform3D: + CATransform3DConcat(perspective, CATransform3DMakeRotation(CGFloat(M_PI), 0, 1, 0))) + animation.duration = CFTimeInterval(duration) + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + animation.timingFunction = getTimingFunction(curve) + layer.addAnimation(animation, forKey: "3d") + case .FlipY: + var perspective = CATransform3DIdentity + perspective.m34 = -1.0 / layer.frame.size.width/2 + + let animation = CABasicAnimation() + animation.keyPath = "transform" + animation.fromValue = NSValue(CATransform3D: + CATransform3DMakeRotation(0, 0, 0, 0)) + animation.toValue = NSValue(CATransform3D: + CATransform3DConcat(perspective,CATransform3DMakeRotation(CGFloat(M_PI), 1, 0, 0))) + animation.duration = CFTimeInterval(duration) + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + animation.timingFunction = getTimingFunction(curve) + layer.addAnimation(animation, forKey: "3d") + case .Morph: + let morphX = CAKeyframeAnimation() + morphX.keyPath = "transform.scale.x" + morphX.values = [1, 1.3*force, 0.7, 1.3*force, 1] + morphX.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + morphX.timingFunction = getTimingFunction(curve) + morphX.duration = CFTimeInterval(duration) + morphX.repeatCount = repeatCount + morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(morphX, forKey: "morphX") + + let morphY = CAKeyframeAnimation() + morphY.keyPath = "transform.scale.y" + morphY.values = [1, 0.7, 1.3*force, 0.7, 1] + morphY.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + morphY.timingFunction = getTimingFunction(curve) + morphY.duration = CFTimeInterval(duration) + morphY.repeatCount = repeatCount + morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(morphY, forKey: "morphY") + case .Squeeze: + let morphX = CAKeyframeAnimation() + morphX.keyPath = "transform.scale.x" + morphX.values = [1, 1.5*force, 0.5, 1.5*force, 1] + morphX.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + morphX.timingFunction = getTimingFunction(curve) + morphX.duration = CFTimeInterval(duration) + morphX.repeatCount = repeatCount + morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(morphX, forKey: "morphX") + + let morphY = CAKeyframeAnimation() + morphY.keyPath = "transform.scale.y" + morphY.values = [1, 0.5, 1, 0.5, 1] + morphY.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + morphY.timingFunction = getTimingFunction(curve) + morphY.duration = CFTimeInterval(duration) + morphY.repeatCount = repeatCount + morphY.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(morphY, forKey: "morphY") + case .Flash: + let animation = CABasicAnimation() + animation.keyPath = "opacity" + animation.fromValue = 1 + animation.toValue = 0 + animation.duration = CFTimeInterval(duration) + animation.repeatCount = repeatCount * 2.0 + animation.autoreverses = true + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(animation, forKey: "flash") + case .Wobble: + let animation = CAKeyframeAnimation() + animation.keyPath = "transform.rotation" + animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] + animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + animation.duration = CFTimeInterval(duration) + animation.additive = true + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(animation, forKey: "wobble") + + let x = CAKeyframeAnimation() + x.keyPath = "position.x" + x.values = [0, 30*force, -30*force, 30*force, 0] + x.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + x.timingFunction = getTimingFunction(curve) + x.duration = CFTimeInterval(duration) + x.additive = true + x.repeatCount = repeatCount + x.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(x, forKey: "x") + case .Swing: + let animation = CAKeyframeAnimation() + animation.keyPath = "transform.rotation" + animation.values = [0, 0.3*force, -0.3*force, 0.3*force, 0] + animation.keyTimes = [0, 0.2, 0.4, 0.6, 0.8, 1] + animation.duration = CFTimeInterval(duration) + animation.additive = true + animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) + layer.addAnimation(animation, forKey: "swing") + } } } - func getTimingFunction(curve: String) -> CAMediaTimingFunction { switch curve { case "easeIn": From 59fbf0e36fab78cea7447741f1b082659229025d Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 13:38:35 +0200 Subject: [PATCH 046/113] Update Example Project. --- Spring/Spring.swift | 2 +- SpringApp/SpringViewController.swift | 68 ++++++++++++++-------------- 2 files changed, 36 insertions(+), 34 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 92312fc..c7f6666 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -102,7 +102,7 @@ public class Spring : NSObject { private var transform : CGAffineTransform { get { return view.transform } set { view.transform = newValue }} private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } - enum AnimationPreset: String { + public enum AnimationPreset: String { case SlideLeft = "slideLeft" case SlideRight = "slideRight" case SlideDown = "slideDown" diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index a401517..712c2da 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -98,8 +98,8 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView ballView.y = selectedY ballView.rotate = selectedRotate - ballView.animation = data[0][selectedRow] - ballView.curve = data[1][selectedEasing] + ballView.animation = animations[selectedRow].rawValue + ballView.curve = data[selectedEasing] } func minimizeView(sender: AnyObject) { @@ -115,35 +115,37 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView }) UIApplication.sharedApplication().setStatusBarStyle(UIStatusBarStyle.Default, animated: true) } - - var data = [[ - "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", - ], ["spring", "linear", "easeIn", "easeOut", "easeInOut","easeInSine","easeOutSine","easeInOutSine","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInBack","easeOutBack","easeInOutBack"]] + + 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 data = ["spring", "linear", "easeIn", "easeOut", "easeInOut","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() @@ -210,11 +212,11 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return data[component].count + return component == 0 ? animations.count : data.count } func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { - return data[component][row] + return component == 0 ? animations[row].rawValue : data[row] } func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { From e2a89bf2434d221620fce001e39e2e17219f856f Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 14:12:11 +0200 Subject: [PATCH 047/113] Add animation curve enumeration. --- Spring/Spring.swift | 32 ++++++++++++++++++++++++++++++++ 1 file changed, 32 insertions(+) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index c7f6666..19deb14 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -132,6 +132,38 @@ public class Spring : NSObject { 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) { From 3315e69027dc43c13bdd4c3cff8a46cc7f319098 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 14:17:59 +0200 Subject: [PATCH 048/113] Use animation curve enum in switch statement --- Spring/Spring.swift | 124 ++++++++++++++++++++++---------------------- 1 file changed, 63 insertions(+), 61 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 19deb14..6a9bd54 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -365,69 +365,71 @@ public class Spring : NSObject { } func getTimingFunction(curve: String) -> CAMediaTimingFunction { - switch curve { - case "easeIn": - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) - case "easeOut": - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - case "easeInOut": - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - case "linear": - return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) - 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) - default: - return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault) + if let curve = AnimationCurve(rawValue: curve) { + switch curve { + case .EaseIn: + return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) + case .EaseOut: + return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + case .EaseInOut: + return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + case .Linear: + return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) + 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: kCAMediaTimingFunctionDefault) } + func getAnimationOptions(curve: String) -> UIViewAnimationOptions { switch curve { case "easeIn": From 9e088ac2c9bac23e38d46db5e6ec997617066c4e Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 14:23:33 +0200 Subject: [PATCH 049/113] Update Example Project. --- SpringApp/SpringViewController.swift | 38 +++++++++++++++++++++++++--- 1 file changed, 34 insertions(+), 4 deletions(-) diff --git a/SpringApp/SpringViewController.swift b/SpringApp/SpringViewController.swift index 712c2da..822907b 100644 --- a/SpringApp/SpringViewController.swift +++ b/SpringApp/SpringViewController.swift @@ -99,7 +99,7 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView ballView.rotate = selectedRotate ballView.animation = animations[selectedRow].rawValue - ballView.curve = data[selectedEasing] + ballView.curve = animationCurves[selectedEasing].rawValue } func minimizeView(sender: AnyObject) { @@ -145,7 +145,37 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView .Flash ] - var data = ["spring", "linear", "easeIn", "easeOut", "easeInOut","easeInSine","easeOutSine","easeInOutSine","easeInQuad","easeOutQuad","easeInOutQuad","easeInCubic","easeOutCubic","easeInOutCubic","easeInQuart","easeOutQuart","easeInOutQuart","easeInQuint","easeOutQuint","easeInOutQuint","easeInExpo","easeOutExpo","easeInOutExpo","easeInCirc","easeOutCirc","easeInOutCirc","easeInBack","easeOutBack","easeInOutBack"] + 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() @@ -212,11 +242,11 @@ class SpringViewController: UIViewController, UIPickerViewDelegate, UIPickerView } func pickerView(pickerView: UIPickerView, numberOfRowsInComponent component: Int) -> Int { - return component == 0 ? animations.count : data.count + return component == 0 ? animations.count : animationCurves.count } func pickerView(pickerView: UIPickerView, titleForRow row: Int, forComponent component: Int) -> String! { - return component == 0 ? animations[row].rawValue : data[row] + return component == 0 ? animations[row].rawValue : animationCurves[row].rawValue } func pickerView(pickerView: UIPickerView, didSelectRow row: Int, inComponent component: Int) { From a69baf52b04f43eacbbf49d0aa16c433250d4872 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 14:30:16 +0200 Subject: [PATCH 050/113] Use animation curve enumueration. --- Spring/Spring.swift | 21 ++++++++------------- 1 file changed, 8 insertions(+), 13 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 6a9bd54..bb0c120 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -431,20 +431,15 @@ public class Spring : NSObject { } func getAnimationOptions(curve: String) -> UIViewAnimationOptions { - switch curve { - case "easeIn": - return UIViewAnimationOptions.CurveEaseIn - case "easeOut": - return UIViewAnimationOptions.CurveEaseOut - case "easeInOut": - return UIViewAnimationOptions.CurveEaseInOut - case "linear": - return UIViewAnimationOptions.CurveLinear - case "spring": - return UIViewAnimationOptions.CurveLinear - default: - return UIViewAnimationOptions.CurveLinear + if let curve = AnimationCurve(rawValue: curve) { + switch curve { + case .EaseIn: return UIViewAnimationOptions.CurveEaseIn + case .EaseOut: return UIViewAnimationOptions.CurveEaseOut + case .EaseInOut: return UIViewAnimationOptions.CurveEaseInOut + default: break + } } + return UIViewAnimationOptions.CurveLinear } public func animate() { From 5b10d20e8421ad56575df4096a89eb4bb7e637ff Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 14:39:30 +0200 Subject: [PATCH 051/113] Refactor. --- Spring/Spring.swift | 87 +++++++++++++++------------------------------ 1 file changed, 29 insertions(+), 58 deletions(-) diff --git a/Spring/Spring.swift b/Spring/Spring.swift index bb0c120..9ec4bb2 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -367,64 +367,35 @@ public class Spring : NSObject { func getTimingFunction(curve: String) -> CAMediaTimingFunction { if let curve = AnimationCurve(rawValue: curve) { switch curve { - case .EaseIn: - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseIn) - case .EaseOut: - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) - case .EaseInOut: - return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) - case .Linear: - return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) - 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: kCAMediaTimingFunctionEaseIn) + case .EaseOut: return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseOut) + case .EaseInOut: return CAMediaTimingFunction(name: kCAMediaTimingFunctionEaseInEaseOut) + case .Linear: return CAMediaTimingFunction(name: kCAMediaTimingFunctionLinear) + 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: kCAMediaTimingFunctionDefault) From c5abc116943aff27b8d5f0cbc0ffbfda857b48c8 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Tue, 14 Jul 2015 15:41:14 +0200 Subject: [PATCH 052/113] Fix Xcode 7 beta 3 warnings. --- SpringApp.xcodeproj/project.pbxproj | 16 ---------------- .../xcshareddata/xcschemes/SpringApp.xcscheme | 8 ++++---- 2 files changed, 4 insertions(+), 20 deletions(-) diff --git a/SpringApp.xcodeproj/project.pbxproj b/SpringApp.xcodeproj/project.pbxproj index 3bc52d5..8ac99e0 100644 --- a/SpringApp.xcodeproj/project.pbxproj +++ b/SpringApp.xcodeproj/project.pbxproj @@ -640,10 +640,6 @@ 1A4FDA511A6E44780099D309 /* Debug */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -660,10 +656,6 @@ 1A4FDA521A6E44780099D309 /* Release */ = { isa = XCBuildConfiguration; buildSettings = { - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); INFOPLIST_FILE = SpringTests/Info.plist; IPHONEOS_DEPLOYMENT_TARGET = 8.1; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; @@ -781,10 +773,6 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); GCC_PREPROCESSOR_DEFINITIONS = ( "DEBUG=1", "$(inherited)", @@ -801,10 +789,6 @@ isa = XCBuildConfiguration; buildSettings = { BUNDLE_LOADER = "$(TEST_HOST)"; - FRAMEWORK_SEARCH_PATHS = ( - "$(SDKROOT)/Developer/Library/Frameworks", - "$(inherited)", - ); INFOPLIST_FILE = SpringAppTests/Info.plist; LD_RUNPATH_SEARCH_PATHS = "$(inherited) @executable_path/Frameworks @loader_path/Frameworks"; PRODUCT_BUNDLE_IDENTIFIER = "designcode.$(PRODUCT_NAME:rfc1034identifier)"; diff --git a/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme b/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme index ed9fc4a..d4dc8bd 100644 --- a/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme +++ b/SpringApp.xcodeproj/xcshareddata/xcschemes/SpringApp.xcscheme @@ -51,10 +51,10 @@ + shouldUseLaunchSchemeArgsEnv = "YES"> @@ -90,11 +90,11 @@ From fae14d1f1d42156b73720b86363a862e68855206 Mon Sep 17 00:00:00 2001 From: =?UTF-8?q?Andre=CC=81=20Schneider?= Date: Thu, 16 Jul 2015 08:42:55 +0200 Subject: [PATCH 053/113] Fix damping slider thumb tint color. --- SpringApp/Base.lproj/Main.storyboard | 29 ++++++++++++++-------------- 1 file changed, 14 insertions(+), 15 deletions(-) diff --git a/SpringApp/Base.lproj/Main.storyboard b/SpringApp/Base.lproj/Main.storyboard index 1b4a473..c651883 100644 --- a/SpringApp/Base.lproj/Main.storyboard +++ b/SpringApp/Base.lproj/Main.storyboard @@ -1,7 +1,7 @@ - + - + @@ -172,19 +172,19 @@