diff --git a/Spring/AsyncButton.swift b/Spring/AsyncButton.swift index 7d9f2db..d7c6473 100644 --- a/Spring/AsyncButton.swift +++ b/Spring/AsyncButton.swift @@ -23,29 +23,25 @@ import UIKit public class AsyncButton: UIButton { - - private var imageURL = [UInt:NSURL]() - private var placeholderImage = [UInt:UIImage]() - - + + 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: urlString) { [weak self] image, url in - - if let strongSelf = self { - - DispatchQueue.main.async(execute: { () -> Void in - if strongSelf.imageURL[state.rawValue]?.absoluteString == url { - strongSelf.setImage(image, for: state) - } - }) + + guard let urlString = url?.absoluteString else { return } + ImageLoader.sharedLoader.image(for: urlString) { [weak self] image, url in + guard let strongSelf = self else { return } + DispatchQueue.main.async(execute: { + if strongSelf.imageURL[state.rawValue]?.absoluteString == url { + strongSelf.setImage(image, for: state) } - } + }) } } - + } + diff --git a/Spring/AsyncImageView.swift b/Spring/AsyncImageView.swift index aa2f7e8..0501696 100644 --- a/Spring/AsyncImageView.swift +++ b/Spring/AsyncImageView.swift @@ -29,16 +29,14 @@ public class AsyncImageView: UIImageView { public var url : NSURL? { didSet { self.image = placeholderImage - if let urlString = url?.absoluteString { - ImageLoader.sharedLoader.imageForUrl(urlString: urlString) { [weak self] image, url in - if let strongSelf = self { - DispatchQueue.main.async(execute: { () -> Void in - if strongSelf.url?.absoluteString == url { - strongSelf.image = image ?? strongSelf.placeholderImage - } - }) + guard let urlString = url?.absoluteString else { return } + ImageLoader.sharedLoader.image(for: urlString) { [weak self] image, url in + guard let strongSelf = self else { return } + DispatchQueue.main.async(execute: { + if strongSelf.url?.absoluteString == url { + strongSelf.image = image ?? strongSelf.placeholderImage } - } + }) } } } @@ -49,3 +47,4 @@ public class AsyncImageView: UIImageView { } } + diff --git a/Spring/AutoTextView.swift b/Spring/AutoTextView.swift index 1d0c7e6..a594d72 100644 --- a/Spring/AutoTextView.swift +++ b/Spring/AutoTextView.swift @@ -17,11 +17,12 @@ public class AutoTextView: UITextView { if text.length == 0 { size.height = 0 } - + contentInset = UIEdgeInsets(top: -4, left: -4, bottom: -4, right: -4) layoutIfNeeded() - + return size } } } + diff --git a/Spring/BlurView.swift b/Spring/BlurView.swift index 2defcf6..f85ca16 100644 --- a/Spring/BlurView.swift +++ b/Spring/BlurView.swift @@ -23,11 +23,12 @@ import UIKit public func insertBlurView (view: UIView, style: UIBlurEffectStyle) -> UIVisualEffectView { - view.backgroundColor = UIColor.clear - + view.backgroundColor = .clear + let blurEffect = UIBlurEffect(style: style) let blurEffectView = UIVisualEffectView(effect: blurEffect) blurEffectView.frame = view.bounds view.insertSubview(blurEffectView, at: 0) return blurEffectView } + diff --git a/Spring/DesignableButton.swift b/Spring/DesignableButton.swift index 0612083..4d63be9 100644 --- a/Spring/DesignableButton.swift +++ b/Spring/DesignableButton.swift @@ -24,42 +24,42 @@ import UIKit @IBDesignable public class DesignableButton: SpringButton { - @IBInspectable public var borderColor: UIColor = UIColor.clear { + @IBInspectable public var borderColor: UIColor = .clear { didSet { layer.borderColor = borderColor.cgColor } } - + @IBInspectable public var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } - + @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius } } - - @IBInspectable public var shadowColor: UIColor = UIColor.clear { + + @IBInspectable public var shadowColor: UIColor = .clear { didSet { layer.shadowColor = shadowColor.cgColor } } - + @IBInspectable public var shadowRadius: CGFloat = 0 { didSet { layer.shadowRadius = shadowRadius } } - + @IBInspectable public var shadowOpacity: CGFloat = 0 { didSet { layer.shadowOpacity = Float(shadowOpacity) } } - + @IBInspectable public var shadowOffsetY: CGFloat = 0 { didSet { layer.shadowOffset.height = shadowOffsetY @@ -67,3 +67,4 @@ import UIKit } } + diff --git a/Spring/DesignableImageView.swift b/Spring/DesignableImageView.swift index 32a90a2..d4b323a 100644 --- a/Spring/DesignableImageView.swift +++ b/Spring/DesignableImageView.swift @@ -23,19 +23,19 @@ import UIKit @IBDesignable public class DesignableImageView: SpringImageView { - - @IBInspectable public var borderColor: UIColor = UIColor.clear { + + @IBInspectable public var borderColor: UIColor = .clear { didSet { layer.borderColor = borderColor.cgColor } } - + @IBInspectable public var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } - + @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius @@ -43,3 +43,4 @@ import UIKit } } + diff --git a/Spring/DesignableLabel.swift b/Spring/DesignableLabel.swift index 0520d77..25120a2 100644 --- a/Spring/DesignableLabel.swift +++ b/Spring/DesignableLabel.swift @@ -28,16 +28,18 @@ import UIKit didSet { let font = UIFont(name: self.font.fontName, size: self.font.pointSize) guard let text = self.text else { return } - + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight - + let attributedString = NSMutableAttributedString(string: text) - attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSMakeRange(0, attributedString.length)) - attributedString.addAttribute(NSAttributedStringKey.font, value: font!, range: NSMakeRange(0, attributedString.length)) - + + attributedString.add(attribute: .paragraphStyle, value: paragraphStyle) + attributedString.add(attribute: .font, value: font!) + self.attributedText = attributedString } } } + diff --git a/Spring/DesignableTabBarController.swift b/Spring/DesignableTabBarController.swift index dc55036..00a1226 100644 --- a/Spring/DesignableTabBarController.swift +++ b/Spring/DesignableTabBarController.swift @@ -23,78 +23,78 @@ import UIKit @IBDesignable class DesignableTabBarController: UITabBarController { - - @IBInspectable var normalTint: UIColor = UIColor.clear { + + @IBInspectable var normalTint: UIColor = .clear { didSet { UITabBar.appearance().tintColor = normalTint - UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: normalTint], for: UIControlState()) + UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor: normalTint], for: []) } } - - @IBInspectable var selectedTint: UIColor = UIColor.clear { + + @IBInspectable var selectedTint: UIColor = .clear { didSet { UITabBar.appearance().tintColor = selectedTint - UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: selectedTint], for:UIControlState.selected) + UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor: selectedTint], for: .selected) } } - + @IBInspectable var fontName: String = "" { didSet { - UITabBarItem.appearance().setTitleTextAttributes([NSAttributedStringKey.foregroundColor: normalTint, NSAttributedStringKey.font: UIFont(name: fontName, size: 11)!], for: UIControlState()) + UITabBarItem.appearance().setTitleTextAttributes([.foregroundColor: normalTint, .font: UIFont(name: fontName, size: 11)!], for: []) } } - + @IBInspectable var firstSelectedImage: UIImage? { didSet { if let image = firstSelectedImage { var tabBarItems = self.tabBar.items as [UITabBarItem]! - tabBarItems?[0].selectedImage = image.withRenderingMode(UIImageRenderingMode.alwaysTemplate) + tabBarItems?[0].selectedImage = image.withRenderingMode(.alwaysTemplate) } } } - + @IBInspectable var secondSelectedImage: UIImage? { didSet { if let image = secondSelectedImage { var tabBarItems = self.tabBar.items as [UITabBarItem]! - tabBarItems?[1].selectedImage = image.withRenderingMode(UIImageRenderingMode.alwaysTemplate) + tabBarItems?[1].selectedImage = image.withRenderingMode(.alwaysTemplate) } } } - + @IBInspectable var thirdSelectedImage: UIImage? { didSet { if let image = thirdSelectedImage { var tabBarItems = self.tabBar.items as [UITabBarItem]! - tabBarItems?[2].selectedImage = image.withRenderingMode(UIImageRenderingMode.alwaysTemplate) + tabBarItems?[2].selectedImage = image.withRenderingMode(.alwaysTemplate) } } } - + @IBInspectable var fourthSelectedImage: UIImage? { didSet { if let image = fourthSelectedImage { var tabBarItems = self.tabBar.items as [UITabBarItem]! - tabBarItems?[3].selectedImage = image.withRenderingMode(UIImageRenderingMode.alwaysTemplate) + tabBarItems?[3].selectedImage = image.withRenderingMode(.alwaysTemplate) } } } - + @IBInspectable var fifthSelectedImage: UIImage? { didSet { if let image = fifthSelectedImage { var tabBarItems = self.tabBar.items as [UITabBarItem]! - tabBarItems?[4].selectedImage = image.withRenderingMode(UIImageRenderingMode.alwaysTemplate) + tabBarItems?[4].selectedImage = image.withRenderingMode(.alwaysTemplate) } } } - + override func viewDidLoad() { super.viewDidLoad() - + for item in self.tabBar.items as [UITabBarItem]! { if let image = item.image { - item.image = image.imageWithColor(tintColor: self.normalTint).withRenderingMode(UIImageRenderingMode.alwaysOriginal) + item.image = image.imageWithColor(tintColor: self.normalTint).withRenderingMode(.alwaysOriginal) } } } @@ -103,20 +103,21 @@ import UIKit extension UIImage { func imageWithColor(tintColor: UIColor) -> UIImage { UIGraphicsBeginImageContextWithOptions(self.size, false, self.scale) - + let context = UIGraphicsGetCurrentContext() context!.translateBy(x: 0, y: self.size.height) context!.scaleBy(x: 1.0, y: -1.0); - context!.setBlendMode(CGBlendMode.normal) - - let rect = CGRect(x: 0, y: 0, width: self.size.width, height: self.size.height) + context!.setBlendMode(.normal) + + let rect = CGRect(origin: .zero, size: self.size) context?.clip(to: rect, mask: self.cgImage!) tintColor.setFill() context!.fill(rect) - + let newImage = UIGraphicsGetImageFromCurrentImageContext()! as UIImage UIGraphicsEndImageContext() - + return newImage } } + diff --git a/Spring/DesignableTextField.swift b/Spring/DesignableTextField.swift index edc5a2b..f80b275 100644 --- a/Spring/DesignableTextField.swift +++ b/Spring/DesignableTextField.swift @@ -23,78 +23,79 @@ import UIKit @IBDesignable public class DesignableTextField: SpringTextField { - - @IBInspectable public var placeholderColor: UIColor = UIColor.clear { + + @IBInspectable public var placeholderColor: UIColor = .clear { didSet { guard let placeholder = placeholder else { return } - attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [NSAttributedStringKey.foregroundColor: placeholderColor]) + attributedPlaceholder = NSAttributedString(string: placeholder, attributes: [.foregroundColor: placeholderColor]) layoutSubviews() - + } } - + @IBInspectable public var sidePadding: CGFloat = 0 { didSet { let padding = UIView(frame: CGRect(x: 0, y: 0, width: sidePadding, height: sidePadding)) - - leftViewMode = UITextFieldViewMode.always + + leftViewMode = .always leftView = padding - - rightViewMode = UITextFieldViewMode.always + + rightViewMode = .always rightView = padding } } - + @IBInspectable public var leftPadding: CGFloat = 0 { didSet { let padding = UIView(frame: CGRect(x: 0, y: 0, width: leftPadding, height: 0)) - - leftViewMode = UITextFieldViewMode.always + + leftViewMode = .always leftView = padding } } - + @IBInspectable public var rightPadding: CGFloat = 0 { didSet { let padding = UIView(frame: CGRect(x: 0, y: 0, width: rightPadding, height: 0)) - - rightViewMode = UITextFieldViewMode.always + + rightViewMode = .always rightView = padding } } - - @IBInspectable public var borderColor: UIColor = UIColor.clear { + + @IBInspectable public var borderColor: UIColor = .clear { didSet { layer.borderColor = borderColor.cgColor } } - + @IBInspectable public var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } - + @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius } } - + @IBInspectable public var lineHeight: CGFloat = 1.5 { didSet { let font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) guard let text = self.text else { return } - + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight - + let attributedString = NSMutableAttributedString(string: text) - attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length)) - attributedString.addAttribute(NSAttributedStringKey.font, value: font!, range: NSRange(location: 0, length: attributedString.length)) - + attributedString.add(attribute:.paragraphStyle, value: paragraphStyle) + attributedString.add(attribute:.font, value: font!) + self.attributedText = attributedString } } - + } + diff --git a/Spring/DesignableTextView.swift b/Spring/DesignableTextView.swift index 3db40b3..adf8afa 100644 --- a/Spring/DesignableTextView.swift +++ b/Spring/DesignableTextView.swift @@ -23,19 +23,19 @@ import UIKit @IBDesignable public class DesignableTextView: SpringTextView { - - @IBInspectable public var borderColor: UIColor = UIColor.clear { + + @IBInspectable public var borderColor: UIColor = .clear { didSet { layer.borderColor = borderColor.cgColor } } - + @IBInspectable public var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } - + @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius @@ -46,16 +46,17 @@ import UIKit didSet { let font = UIFont(name: self.font!.fontName, size: self.font!.pointSize) guard let text = self.text else { return } - + let paragraphStyle = NSMutableParagraphStyle() paragraphStyle.lineSpacing = lineHeight let attributedString = NSMutableAttributedString(string: text) - attributedString.addAttribute(NSAttributedStringKey.paragraphStyle, value: paragraphStyle, range: NSRange(location: 0, length: attributedString.length)) - attributedString.addAttribute(NSAttributedStringKey.font, value: font!, range: NSRange(location: 0, length: attributedString.length)) - + attributedString.add(attribute: .paragraphStyle, value: paragraphStyle) + attributedString.add(attribute: .font, value: font!) + self.attributedText = attributedString } } } + diff --git a/Spring/DesignableView.swift b/Spring/DesignableView.swift index a82d23f..4fe69d5 100644 --- a/Spring/DesignableView.swift +++ b/Spring/DesignableView.swift @@ -23,46 +23,47 @@ import UIKit @IBDesignable public class DesignableView: SpringView { - - @IBInspectable public var borderColor: UIColor = UIColor.clear { + + @IBInspectable public var borderColor: UIColor = .clear { didSet { layer.borderColor = borderColor.cgColor } } - + @IBInspectable public var borderWidth: CGFloat = 0 { didSet { layer.borderWidth = borderWidth } } - + @IBInspectable public var cornerRadius: CGFloat = 0 { didSet { layer.cornerRadius = cornerRadius } } - - @IBInspectable public var shadowColor: UIColor = UIColor.clear { + + @IBInspectable public var shadowColor: UIColor = .clear { didSet { layer.shadowColor = shadowColor.cgColor } } - + @IBInspectable public var shadowRadius: CGFloat = 0 { didSet { layer.shadowRadius = shadowRadius } } - + @IBInspectable public var shadowOpacity: CGFloat = 0 { didSet { layer.shadowOpacity = Float(shadowOpacity) } } - + @IBInspectable public var shadowOffsetY: CGFloat = 0 { didSet { layer.shadowOffset.height = shadowOffsetY } } } + diff --git a/Spring/ImageLoader.swift b/Spring/ImageLoader.swift index bcb626d..90cf56b 100755 --- a/Spring/ImageLoader.swift +++ b/Spring/ImageLoader.swift @@ -25,23 +25,23 @@ import Foundation public class ImageLoader { - + var cache = NSCache() - + public class var sharedLoader : ImageLoader { struct Static { static let instance : ImageLoader = ImageLoader() } return Static.instance } - - public func imageForUrl(urlString: String, completionHandler: @escaping(_ image: UIImage?, _ url: String) -> ()) { - DispatchQueue.global(qos: DispatchQoS.QoSClass.background).async { + + public func image(for urlString: String, completionHandler: @escaping(_ image: UIImage?, _ url: String) -> ()) { + DispatchQueue.global(qos: .background).async { var data: NSData? - + if let dataCache = self.cache.object(forKey: urlString as NSString){ data = (dataCache) as NSData - + }else{ if (URL(string: urlString) != nil) { @@ -53,7 +53,7 @@ public class ImageLoader { return } } - + if let goodData = data { let image = UIImage(data: goodData as Data) DispatchQueue.main.async(execute: {() in @@ -61,14 +61,14 @@ public class ImageLoader { }) return } - + let downloadTask: URLSessionDataTask = URLSession.shared.dataTask(with: URL(string: urlString)!, completionHandler: { (data, response, error) -> Void in - + if (error != nil) { completionHandler(nil, urlString) return } - + if data != nil { let image = UIImage(data: data!) self.cache.setObject(data! as NSData, forKey: urlString as NSString) @@ -79,8 +79,9 @@ public class ImageLoader { } }) downloadTask.resume() - + } - + } } + diff --git a/Spring/KeyboardLayoutConstraint.swift b/Spring/KeyboardLayoutConstraint.swift index 79dc8cb..79a04bb 100644 --- a/Spring/KeyboardLayoutConstraint.swift +++ b/Spring/KeyboardLayoutConstraint.swift @@ -23,84 +23,80 @@ import UIKit public class KeyboardLayoutConstraint: NSLayoutConstraint { - + private var offset : CGFloat = 0 private var keyboardVisibleHeight : CGFloat = 0 - + override public func awakeFromNib() { super.awakeFromNib() - + offset = constant - - NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillShowNotification(_:)), name: NSNotification.Name.UIKeyboardWillShow, object: nil) - NotificationCenter.default.addObserver(self, selector: #selector(KeyboardLayoutConstraint.keyboardWillHideNotification(_:)), name: NSNotification.Name.UIKeyboardWillHide, object: nil) + + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillShowNotification), name: .UIKeyboardWillShow, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(keyboardWillHideNotification), name: .UIKeyboardWillHide, object: nil) } - + deinit { NotificationCenter.default.removeObserver(self) } - + // MARK: Notification - + @objc func keyboardWillShowNotification(_ notification: Notification) { - if let userInfo = notification.userInfo { - if let frameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { - let frame = frameValue.cgRectValue - keyboardVisibleHeight = frame.size.height - } - - self.updateConstant() - switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { - case let (.some(duration), .some(curve)): - - let options = UIViewAnimationOptions(rawValue: curve.uintValue) - - UIView.animate( - withDuration: TimeInterval(duration.doubleValue), - delay: 0, - options: options, - animations: { - UIApplication.shared.keyWindow?.layoutIfNeeded() - return - }, completion: { finished in - }) - default: - - break - } - + guard let userInfo = notification.userInfo else { return } + if let frameValue = userInfo[UIKeyboardFrameEndUserInfoKey] as? NSValue { + let frame = frameValue.cgRectValue + keyboardVisibleHeight = frame.size.height + } + + self.updateConstant() + switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { + case let (.some(duration), .some(curve)): + + let options = UIViewAnimationOptions(rawValue: curve.uintValue) + + UIView.animate( + withDuration: TimeInterval(duration.doubleValue), + delay: 0, + options: options, + animations: { + UIApplication.shared.keyWindow?.layoutIfNeeded() + return + }, completion: { finished in + }) + default: + break } - } - + @objc func keyboardWillHideNotification(_ notification: NSNotification) { keyboardVisibleHeight = 0 self.updateConstant() - - if let userInfo = notification.userInfo { - - switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { - case let (.some(duration), .some(curve)): - - let options = UIViewAnimationOptions(rawValue: curve.uintValue) - - UIView.animate( - withDuration: TimeInterval(duration.doubleValue), - delay: 0, - options: options, - animations: { - UIApplication.shared.keyWindow?.layoutIfNeeded() - return - }, completion: { finished in - }) - default: - break - } + + guard let userInfo = notification.userInfo else { return } + + switch (userInfo[UIKeyboardAnimationDurationUserInfoKey] as? NSNumber, userInfo[UIKeyboardAnimationCurveUserInfoKey] as? NSNumber) { + case let (.some(duration), .some(curve)): + + let options = UIViewAnimationOptions(rawValue: curve.uintValue) + + UIView.animate( + withDuration: TimeInterval(duration.doubleValue), + delay: 0, + options: options, + animations: { + UIApplication.shared.keyWindow?.layoutIfNeeded() + return + }, completion: { finished in + }) + default: + break } } - + func updateConstant() { self.constant = offset + keyboardVisibleHeight } - + } + diff --git a/Spring/LoadingView.swift b/Spring/LoadingView.swift index 047aaa9..cd50f58 100644 --- a/Spring/LoadingView.swift +++ b/Spring/LoadingView.swift @@ -37,7 +37,7 @@ public class LoadingView: UIView { } class func designCodeLoadingView() -> UIView { - + return Bundle(for: self).loadNibNamed("LoadingView", owner: self, options: nil)![0] as! UIView } } @@ -81,3 +81,4 @@ public extension UIView { } } + diff --git a/Spring/Misc.swift b/Spring/Misc.swift index 2a80c01..20af23f 100644 --- a/Spring/Misc.swift +++ b/Spring/Misc.swift @@ -24,14 +24,21 @@ import UIKit public extension String { public var length: Int { return self.characters.count } - + public func toURL() -> NSURL? { return NSURL(string: self) } } +extension NSMutableAttributedString { + func add(attribute : NSAttributedStringKey, value : T) { + let range = NSRange(location: 0, length: length) + addAttribute(attribute, value: value, range: range) + } +} + public func htmlToAttributedString(text: String) -> NSAttributedString! { - guard let htmlData = text.data(using: String.Encoding.utf8, allowLossyConversion: false) else { + guard let htmlData = text.data(using: .utf8, allowLossyConversion: false) else { return NSAttributedString() } let htmlString: NSAttributedString? do { @@ -39,16 +46,16 @@ public func htmlToAttributedString(text: String) -> NSAttributedString! { } catch _ { htmlString = nil } - + return htmlString } public func degreesToRadians(degrees: CGFloat) -> CGFloat { - return degrees * CGFloat(CGFloat.pi / 180) + return degrees * .pi / 180 } public func delay(delay:Double, closure: @escaping ()->()) { - DispatchQueue.main.asyncAfter(deadline: DispatchTime.now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure) + DispatchQueue.main.asyncAfter(deadline: .now() + Double(Int64(delay * Double(NSEC_PER_SEC))) / Double(NSEC_PER_SEC), execute: closure) } public func imageFromURL(_ Url: String) -> UIImage { @@ -64,12 +71,12 @@ public extension UIColor { var blue: CGFloat = 0.0 var alpha: CGFloat = 1.0 var hex: String = hex - + if hex.hasPrefix("#") { let index = hex.index(hex.startIndex, offsetBy: 1) hex = hex.substring(from: index) } - + let scanner = Scanner(string: hex) var hexValue: CUnsignedLongLong = 0 if scanner.scanHexInt64(&hexValue) { @@ -103,7 +110,7 @@ public extension UIColor { } public func rgbaToUIColor(red: CGFloat, green: CGFloat, blue: CGFloat, alpha: CGFloat) -> UIColor { - + return UIColor(red: red, green: green, blue: blue, alpha: alpha) } @@ -133,28 +140,28 @@ public func dateFromString(date: String, format: String) -> Date { } public func randomStringWithLength (len : Int) -> NSString { - + let letters : NSString = "abcdefghijklmnopqrstuvwxyzABCDEFGHIJKLMNOPQRSTUVWXYZ0123456789" - + let randomString : NSMutableString = NSMutableString(capacity: len) - + for _ in 0 ..< len { let length = UInt32 (letters.length) let rand = arc4random_uniform(length) randomString.appendFormat("%C", letters.character(at: Int(rand))) } - + return randomString } public func timeAgoSinceDate(date: Date, numericDates: Bool) -> String { let calendar = Calendar.current - let unitFlags = Set(arrayLiteral: Calendar.Component.minute, Calendar.Component.hour, Calendar.Component.day, Calendar.Component.weekOfYear, Calendar.Component.month, Calendar.Component.year, Calendar.Component.second) + let unitFlags : Set = [.minute, .hour, .day, .weekOfYear, .month, .year, .second] let now = Date() let dateComparison = now.compare(date) var earliest: Date var latest: Date - + switch dateComparison { case .orderedAscending: earliest = now @@ -163,9 +170,9 @@ public func timeAgoSinceDate(date: Date, numericDates: Bool) -> String { earliest = date latest = now } - + let components: DateComponents = calendar.dateComponents(unitFlags, from: earliest, to: latest) - + guard let year = components.year, let month = components.month, @@ -175,9 +182,9 @@ public func timeAgoSinceDate(date: Date, numericDates: Bool) -> String { let minute = components.minute, let second = components.second else { - fatalError() + fatalError() } - + if (year >= 2) { return "\(year)y" } else if (year >= 1) { @@ -231,7 +238,7 @@ public func timeAgoSinceDate(date: Date, numericDates: Bool) -> String { } else { return "now" } - + } extension UIImageView { @@ -247,9 +254,9 @@ extension UIImageView { self.image = placeholderImage return } - DispatchQueue.main.async() { () -> Void in + DispatchQueue.main.async() { self.image = image - + } }.resume() } @@ -261,3 +268,4 @@ extension UIImageView { setImage(url: url, contentMode: mode, placeholderImage: placeholderImage) } } + diff --git a/Spring/SoundPlayer.swift b/Spring/SoundPlayer.swift index d2451d9..b7545eb 100644 --- a/Spring/SoundPlayer.swift +++ b/Spring/SoundPlayer.swift @@ -24,37 +24,38 @@ import UIKit import AudioToolbox public struct SoundPlayer { - + static var filename : String? static var enabled : Bool = true - + private struct Internal { - static var cache = [URL:SystemSoundID]() + static var cache : [URL:SystemSoundID] = [:] } - + public static func playSound(soundFile: String) { - + if !enabled { return } - + if let url = Bundle.main.url(forResource: soundFile, withExtension: nil) { - + var soundID : SystemSoundID = Internal.cache[url] ?? 0 - + if soundID == 0 { AudioServicesCreateSystemSoundID(url as CFURL, &soundID) Internal.cache[url] = soundID } - + AudioServicesPlaySystemSound(soundID) - + } else { print("Could not find sound file name `\(soundFile)`") } } - + static func play(file: String) { self.playSound(soundFile: file) } } + diff --git a/Spring/Spring.swift b/Spring/Spring.swift index 5b60b1b..9829583 100644 --- a/Spring/Spring.swift +++ b/Spring/Spring.swift @@ -40,12 +40,12 @@ import UIKit var opacity: CGFloat { get set } var animateFrom: Bool { get set } var curve: String { get set } - + // UIView var layer : CALayer { get } var transform : CGAffineTransform { get set } var alpha : CGFloat { get set } - + func animate() func animateNext(completion: @escaping () -> ()) func animateTo() @@ -53,21 +53,21 @@ import UIKit } public class Spring : NSObject { - + private unowned var view : Springable private var shouldAnimateAfterActive = false private var shouldAnimateInLayoutSubviews = true - + init(_ view: Springable) { self.view = view super.init() commonInit() } - + func commonInit() { - NotificationCenter.default.addObserver(self, selector: #selector(Spring.didBecomeActiveNotification(_:)), name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil) + NotificationCenter.default.addObserver(self, selector: #selector(didBecomeActiveNotification), name: .UIApplicationDidBecomeActive, object: nil) } - + @objc func didBecomeActiveNotification(_ notification: NSNotification) { if shouldAnimateAfterActive { alpha = 0 @@ -75,11 +75,11 @@ public class Spring : NSObject { shouldAnimateAfterActive = false } } - + deinit { - NotificationCenter.default.removeObserver(self, name: NSNotification.Name.UIApplicationDidBecomeActive, object: nil) + NotificationCenter.default.removeObserver(self, name: .UIApplicationDidBecomeActive, object: nil) } - + private var autostart: Bool { set { self.view.autostart = newValue } get { return self.view.autostart }} private var autohide: Bool { set { self.view.autohide = newValue } get { return self.view.autohide }} private var animation: String { set { self.view.animation = newValue } get { return self.view.animation }} @@ -97,12 +97,12 @@ public class Spring : NSObject { private var opacity: CGFloat { set { self.view.opacity = newValue } get { return self.view.opacity }} private var animateFrom: Bool { set { self.view.animateFrom = newValue } get { return self.view.animateFrom }} private var curve: String { set { self.view.curve = newValue } get { return self.view.curve }} - + // UIView private var layer : CALayer { return view.layer } private var transform : CGAffineTransform { get { return view.transform } set { view.transform = newValue }} private var alpha: CGFloat { get { return view.alpha } set { view.alpha = newValue } } - + public enum AnimationPreset: String { case SlideLeft = "slideLeft" case SlideRight = "slideRight" @@ -132,7 +132,7 @@ public class Spring : NSObject { case Wobble = "wobble" case Swing = "swing" } - + public enum AnimationCurve: String { case EaseIn = "easeIn" case EaseOut = "easeOut" @@ -164,7 +164,7 @@ public class Spring : NSObject { case EaseOutBack = "easeOutBack" case EaseInOutBack = "easeInOutBack" } - + func animatePreset() { alpha = 0.99 if let animation = AnimationPreset(rawValue: animation) { @@ -227,7 +227,7 @@ public class Spring : NSObject { scaleY = 2*force case .Fall: animateFrom = false - rotate = 15 * CGFloat(CGFloat.pi/180) + rotate = 15 * .pi/180 y = 600*force case .Shake: let animation = CAKeyframeAnimation() @@ -257,12 +257,12 @@ public class Spring : NSObject { 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(CGFloat.pi), 0, 1, 0))) + CATransform3DConcat(perspective, CATransform3DMakeRotation(.pi, 0, 1, 0))) animation.duration = CFTimeInterval(duration) animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) animation.timingFunction = getTimingFunction(curve: curve) @@ -270,13 +270,13 @@ public class Spring : NSObject { 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(CGFloat.pi), 1, 0, 0))) + CATransform3DConcat(perspective,CATransform3DMakeRotation(.pi, 1, 0, 0))) animation.duration = CFTimeInterval(duration) animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) animation.timingFunction = getTimingFunction(curve: curve) @@ -291,7 +291,7 @@ public class Spring : NSObject { morphX.repeatCount = repeatCount morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(morphX, forKey: "morphX") - + let morphY = CAKeyframeAnimation() morphY.keyPath = "transform.scale.y" morphY.values = [1, 0.7, 1.3*force, 0.7, 1] @@ -311,7 +311,7 @@ public class Spring : NSObject { morphX.repeatCount = repeatCount morphX.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(morphX, forKey: "morphX") - + let morphY = CAKeyframeAnimation() morphY.keyPath = "transform.scale.y" morphY.values = [1, 0.5, 1, 0.5, 1] @@ -340,7 +340,7 @@ public class Spring : NSObject { animation.isAdditive = true animation.beginTime = CACurrentMediaTime() + CFTimeInterval(delay) layer.add(animation, forKey: "wobble") - + let x = CAKeyframeAnimation() x.keyPath = "position.x" x.values = [0, 30*force, -30*force, 30*force, 0] @@ -363,7 +363,7 @@ public class Spring : NSObject { } } } - + func getTimingFunction(curve: String) -> CAMediaTimingFunction { if let curve = AnimationCurve(rawValue: curve) { switch curve { @@ -400,25 +400,25 @@ public class Spring : NSObject { } return CAMediaTimingFunction(name: kCAMediaTimingFunctionDefault) } - + func getAnimationOptions(curve: String) -> UIViewAnimationOptions { if let curve = AnimationCurve(rawValue: curve) { switch curve { - case .EaseIn: return UIViewAnimationOptions.curveEaseIn - case .EaseOut: return UIViewAnimationOptions.curveEaseOut - case .EaseInOut: return UIViewAnimationOptions() + case .EaseIn: return .curveEaseIn + case .EaseOut: return .curveEaseOut + case .EaseInOut: return [] default: break } } - return UIViewAnimationOptions.curveLinear + return .curveLinear } - + public func animate() { animateFrom = true animatePreset() setView {} } - + public func animateNext(completion: @escaping () -> ()) { animateFrom = true animatePreset() @@ -426,13 +426,13 @@ public class Spring : NSObject { completion() } } - + public func animateTo() { animateFrom = false animatePreset() setView {} } - + public func animateToNext(completion: @escaping () -> ()) { animateFrom = false animatePreset() @@ -440,13 +440,13 @@ public class Spring : NSObject { completion() } } - + public func customAwakeFromNib() { if autohide { alpha = 0 } } - + public func customLayoutSubviews() { if shouldAnimateInLayoutSubviews { shouldAnimateInLayoutSubviews = false @@ -460,7 +460,7 @@ public class Spring : NSObject { } } } - + func setView(completion: @escaping () -> ()) { if animateFrom { let translate = CGAffineTransform(translationX: self.x, y: self.y) @@ -468,20 +468,20 @@ public class Spring : NSObject { let rotate = CGAffineTransform(rotationAngle: self.rotate) let translateAndScale = translate.concatenating(scale) self.transform = rotate.concatenating(translateAndScale) - + self.alpha = self.opacity } - + UIView.animate( withDuration: TimeInterval(duration), delay: TimeInterval(delay), usingSpringWithDamping: damping, initialSpringVelocity: velocity, - options: [getAnimationOptions(curve: curve), UIViewAnimationOptions.allowUserInteraction], + options: [getAnimationOptions(curve: curve), .allowUserInteraction], animations: { [weak self] in if let _self = self { if _self.animateFrom { - _self.transform = CGAffineTransform.identity + _self.transform = .identity _self.alpha = 1 } else { @@ -490,27 +490,27 @@ public class Spring : NSObject { let rotate = CGAffineTransform(rotationAngle: _self.rotate) let translateAndScale = translate.concatenating(scale) _self.transform = rotate.concatenating(translateAndScale) - + _self.alpha = _self.opacity } - + } - + }, completion: { [weak self] finished in - + completion() self?.resetAll() - - }) - + + }) + } - + func reset() { x = 0 y = 0 opacity = 1 } - + func resetAll() { x = 0 y = 0 @@ -525,5 +525,6 @@ public class Spring : NSObject { delay = 0 duration = 0.7 } - + } + diff --git a/Spring/SpringAnimation.swift b/Spring/SpringAnimation.swift index e237d3d..0699def 100644 --- a/Spring/SpringAnimation.swift +++ b/Spring/SpringAnimation.swift @@ -32,7 +32,7 @@ import UIKit options: [], animations: { animations() - }, + }, completion: nil ) } @@ -44,7 +44,7 @@ import UIKit options: .curveEaseIn, animations: { animations() - }, + }, completion: nil ) } @@ -56,7 +56,7 @@ import UIKit options: .curveEaseOut, animations: { animations() - }, completion: nil + }, completion: nil ) } @@ -64,10 +64,10 @@ import UIKit UIView.animate( withDuration: duration, delay: 0, - options: UIViewAnimationOptions(), + options: [], animations: { animations() - }, completion: nil + }, completion: nil ) } @@ -78,7 +78,7 @@ import UIKit options: .curveLinear, animations: { animations() - }, completion: nil + }, completion: nil ) } @@ -91,7 +91,7 @@ import UIKit options: [], animations: { animations() - }, completion: nil + }, completion: nil ) } @@ -104,9 +104,10 @@ import UIKit options: [], animations: { animations() - }, completion: { finished in - completion(finished) - } + }, completion: { finished in + completion(finished) + } ) } } + diff --git a/Spring/SpringView.swift b/Spring/SpringView.swift index a00c12a..ca13a8c 100644 --- a/Spring/SpringView.swift +++ b/Spring/SpringView.swift @@ -52,7 +52,7 @@ open class SpringView: UIView, Springable { super.layoutSubviews() spring.customLayoutSubviews() } - + public func animate() { self.spring.animate() } @@ -69,3 +69,4 @@ open class SpringView: UIView, Springable { self.spring.animateToNext(completion: completion) } } + diff --git a/Spring/TransitionManager.swift b/Spring/TransitionManager.swift index 388edac..4030d9a 100644 --- a/Spring/TransitionManager.swift +++ b/Spring/TransitionManager.swift @@ -23,15 +23,15 @@ import UIKit public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { - + var isPresenting = true var duration = 0.3 - + public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let container = transitionContext.containerView - let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)! - let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)! - + let fromView = transitionContext.view(forKey: .from)! + let toView = transitionContext.view(forKey: .to)! + if isPresenting { toView.frame = container.bounds toView.transform = CGAffineTransform(translationX: 0, y: container.frame.size.height) @@ -40,7 +40,7 @@ public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, SpringAnimation.springEaseInOut(duration: duration) { fromView.transform = CGAffineTransform(scaleX: 0.8, y: 0.8) fromView.alpha = 0.5 - toView.transform = CGAffineTransform.identity + toView.transform = .identity } } else { @@ -51,7 +51,7 @@ public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, // the same time take consideration of // previous transformation when presenting let transform = toView.transform - toView.transform = CGAffineTransform.identity + toView.transform = .identity toView.frame = container.bounds toView.transform = transform @@ -60,27 +60,28 @@ public class TransitionManager: NSObject, UIViewControllerTransitioningDelegate, SpringAnimation.springEaseInOut(duration: duration) { fromView.transform = CGAffineTransform(translationX: 0, y: fromView.frame.size.height) - toView.transform = CGAffineTransform.identity + toView.transform = .identity toView.alpha = 1 } } - + delay(delay: duration, closure: { transitionContext.completeTransition(true) }) } - + public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } - + public func animationController(forPresentedController presented: UIViewController, presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { isPresenting = true return self } - + public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { isPresenting = false return self } } + diff --git a/Spring/TransitionZoom.swift b/Spring/TransitionZoom.swift index 6cf5301..07c8c3b 100644 --- a/Spring/TransitionZoom.swift +++ b/Spring/TransitionZoom.swift @@ -23,33 +23,33 @@ import UIKit public class TransitionZoom: NSObject, UIViewControllerTransitioningDelegate, UIViewControllerAnimatedTransitioning { - + var isPresenting = true var duration = 0.4 - + public func animateTransition(using transitionContext: UIViewControllerContextTransitioning) { let container = transitionContext.containerView - let fromView = transitionContext.view(forKey: UITransitionContextViewKey.from)! - let toView = transitionContext.view(forKey: UITransitionContextViewKey.to)! - + let fromView = transitionContext.view(forKey: .from)! + let toView = transitionContext.view(forKey: .to)! + if isPresenting { container.addSubview(fromView) container.addSubview(toView) - + toView.alpha = 0 toView.transform = CGAffineTransform(scaleX: 2, y: 2) SpringAnimation.springEaseInOut(duration: duration) { fromView.transform = CGAffineTransform(scaleX: 0.5, y: 0.5) fromView.alpha = 0 - toView.transform = CGAffineTransform.identity + toView.transform = .identity toView.alpha = 1 } } else { container.addSubview(toView) container.addSubview(fromView) - + SpringAnimation.springEaseInOut(duration: duration) { fromView.transform = CGAffineTransform(scaleX: 2, y: 2) fromView.alpha = 0 @@ -57,23 +57,24 @@ public class TransitionZoom: NSObject, UIViewControllerTransitioningDelegate, UI toView.alpha = 1 } } - + delay(delay: duration, closure: { transitionContext.completeTransition(true) }) } - + public func transitionDuration(using transitionContext: UIViewControllerContextTransitioning?) -> TimeInterval { return duration } - + public func animationController(forPresentedController presented: UIViewController, presenting: UIViewController, sourceController source: UIViewController) -> UIViewControllerAnimatedTransitioning? { isPresenting = true return self } - + public func animationController(forDismissed dismissed: UIViewController) -> UIViewControllerAnimatedTransitioning? { isPresenting = false return self } } +