Compare commits

..

10 Commits

Author SHA1 Message Date
Ivan Vorobei ea32992f63 Update to 1.2.8 2019-02-04 01:34:25 +03:00
Ivan Vorobei 05ba026c1f Update to 1.2.6
Add extenshion to UIViewController. Property `isPresentedAsStork` check if currenct controller present with this pod. For simple usage add func `presentAsStork` - need pass controller only.
2019-02-04 01:20:29 +03:00
Ivan Vorobei b3f49a2a94 Update SPStorkController.podspec 2019-02-01 03:15:56 +03:00
Ivan Vorobei c3aa4dc17e Update SPStorkController.podspec 2019-01-31 22:07:36 +03:00
Ivan Vorobei d9f67b57f8 Update SPStorkController.podspec 2019-01-31 21:49:03 +03:00
Ivan Vorobei 962d1a937d Update to 1.2.2
Add new parametr - `colorIndicator` for change color arrow. Update example & Readme. Fix `SPStorkIndicatorView `
2019-01-31 21:20:53 +03:00
Ivan Vorobei bc6c7ff45e Update README.md 2019-01-31 08:06:47 +03:00
Ivan Vorobei ec7abd4a2a Update example
Update `SparrowKit` pod
2019-01-26 14:01:36 +03:00
Ivan Vorobei 6904e0916a Update UserInterfaceState.xcuserstate 2019-01-21 16:33:48 +03:00
Ivan Vorobei 90ee3d35da Add navigation controller for example 2019-01-21 15:15:54 +03:00
124 changed files with 2462 additions and 1573 deletions
File diff suppressed because it is too large Load Diff
+4 -1
View File
@@ -7,7 +7,10 @@ class AppDelegate: UIResponder, UIApplicationDelegate {
func application(_ application: UIApplication, didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?) -> Bool {
self.launch(rootViewController: Controller())
let navigationController = UINavigationController(rootViewController: Controller())
self.launch(rootViewController: navigationController)
return true
}
+2 -2
View File
@@ -30,7 +30,7 @@ class Controller: UIViewController {
let transitionDelegate = SPStorkTransitioningDelegate()
modal.transitioningDelegate = transitionDelegate
modal.modalPresentationStyle = .custom
present(modal, animated: true, completion: nil)
self.present(modal, animated: true, completion: nil)
}
@objc func presentModalTableViewController() {
@@ -38,6 +38,6 @@ class Controller: UIViewController {
let transitionDelegate = SPStorkTransitioningDelegate()
modal.transitioningDelegate = transitionDelegate
modal.modalPresentationStyle = .custom
present(modal, animated: true, completion: nil)
self.present(modal, animated: true, completion: nil)
}
}
@@ -63,12 +63,3 @@ public struct SPStorkController {
private init() {}
}
extension UIViewController {
var isPresentedAsStork: Bool {
return transitioningDelegate is SPStorkTransitioningDelegate
&& modalPresentationStyle == .custom
&& presentingViewController != nil
}
}
@@ -42,6 +42,13 @@ class SPStorkIndicatorView: UIView {
}
}
var color: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1) {
didSet {
self.leftView.backgroundColor = self.color
self.rightView.backgroundColor = self.color
}
}
private var leftView: UIView = UIView()
private var rightView: UIView = UIView()
@@ -50,8 +57,7 @@ class SPStorkIndicatorView: UIView {
self.backgroundColor = UIColor.clear
self.addSubview(self.leftView)
self.addSubview(self.rightView)
self.leftView.backgroundColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
self.rightView.backgroundColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
self.color = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
}
required init?(coder aDecoder: NSCoder) {
@@ -26,6 +26,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
var isSwipeToDismissEnabled: Bool = true
var isTapAroundToDismissEnabled: Bool = true
var showIndicator: Bool = true
var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
var customHeight: CGFloat? = nil
var transitioningDelegate: SPStorkTransitioningDelegate?
@@ -82,6 +83,7 @@ class SPStorkPresentationController: UIPresentationController, UIGestureRecogniz
guard let containerView = self.containerView, let presentedView = self.presentedView, let window = containerView.window else { return }
if self.showIndicator {
self.indicatorView.color = self.indicatorColor
presentedView.addSubview(self.indicatorView)
}
self.updateLayoutIndicator()
@@ -268,6 +270,8 @@ extension SPStorkPresentationController {
self.workGester = true
self.indicatorView.style = .line
self.presentingViewController.view.layer.removeAllAnimations()
self.presentingViewController.view.endEditing(true)
self.presentedViewController.view.endEditing(true)
gestureRecognizer.setTranslation(CGPoint(x: 0, y: 0), in: containerView)
case .changed:
self.workGester = true
@@ -26,6 +26,7 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
public var isSwipeToDismissEnabled: Bool = true
public var isTapAroundToDismissEnabled: Bool = true
public var showIndicator: Bool = true
public var indicatorColor: UIColor = UIColor.init(red: 202/255, green: 201/255, blue: 207/255, alpha: 1)
public var customHeight: CGFloat? = nil
public func presentationController(forPresented presented: UIViewController, presenting: UIViewController?, source: UIViewController) -> UIPresentationController? {
@@ -33,6 +34,7 @@ public final class SPStorkTransitioningDelegate: NSObject, UIViewControllerTrans
controller.isSwipeToDismissEnabled = self.isSwipeToDismissEnabled
controller.isTapAroundToDismissEnabled = self.isTapAroundToDismissEnabled
controller.showIndicator = self.showIndicator
controller.indicatorColor = self.indicatorColor
controller.customHeight = self.customHeight
controller.transitioningDelegate = self
return controller
@@ -0,0 +1,38 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// 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 UIViewController {
public var isPresentedAsStork: Bool {
return transitioningDelegate is SPStorkTransitioningDelegate
&& modalPresentationStyle == .custom
&& presentingViewController != nil
}
public func presentAsStork(_ controller: UIViewController, complection: (() -> Void)? = nil) {
let transitionDelegate = SPStorkTransitioningDelegate()
controller.transitioningDelegate = transitionDelegate
controller.modalPresentationStyle = .custom
self.present(controller, animated: true, completion: complection)
}
}
@@ -23,7 +23,7 @@ import UIKit
public class SPAnimation {
static func animate(_ duration: TimeInterval,
public static func animate(_ duration: TimeInterval,
animations: (() -> Void)!,
delay: TimeInterval = 0,
options: UIView.AnimationOptions = [],
@@ -40,7 +40,7 @@ public class SPAnimation {
})
}
static func animateWithRepeatition(_ duration: TimeInterval,
public static func animateWithRepeatition(_ duration: TimeInterval,
animations: (() -> Void)!,
delay: TimeInterval = 0,
options: UIView.AnimationOptions = [],
@@ -23,11 +23,11 @@ import UIKit
public class SPAnimationAlpha {
fileprivate static let durationListAnimation: TimeInterval = 0.45
fileprivate static let coefLenthForTransition: CGFloat = 2.8
fileprivate static let delayPerItem: TimeInterval = 0.09
public static let durationListAnimation: TimeInterval = 0.45
public static let coefLenthForTransition: CGFloat = 2.8
public static let delayPerItem: TimeInterval = 0.09
static func hideList(_ duration: TimeInterval = durationListAnimation,
public static func hideList(_ duration: TimeInterval = durationListAnimation,
views: [UIView],
delayPerItem: TimeInterval = delayPerItem,
withComplection completion: (() -> Void)! = {}) {
@@ -51,7 +51,7 @@ public class SPAnimationAlpha {
}
}
static func hideReverseList(_ duration: TimeInterval = durationListAnimation,
public static func hideReverseList(_ duration: TimeInterval = durationListAnimation,
views: [UIView],
delayPerItem: TimeInterval = delayPerItem,
withComplection completion: (() -> Void)! = {}) {
@@ -76,7 +76,7 @@ public class SPAnimationAlpha {
}
}
static func showList(_ duration: TimeInterval = durationListAnimation,
public static func showList(_ duration: TimeInterval = durationListAnimation,
views: [UIView],
delayPerItem: TimeInterval = delayPerItem,
withComplection completion: (() -> Void)! = {}) {
@@ -23,10 +23,10 @@ import UIKit
public class SPAnimationSpring {
fileprivate static let spring: CGFloat = 1
fileprivate static let velocity: CGFloat = 1
public static let spring: CGFloat = 1
public static let velocity: CGFloat = 1
static func animate(_ duration: TimeInterval,
public static func animate(_ duration: TimeInterval,
animations: (() -> Void)!,
delay: TimeInterval = 0,
spring: CGFloat = spring,
@@ -47,7 +47,7 @@ public class SPAnimationSpring {
})
}
static func animateWithRepeatition(_ duration: TimeInterval,
public static func animateWithRepeatition(_ duration: TimeInterval,
animations: (() -> Void)!,
delay: TimeInterval = 0,
spring: CGFloat = spring,
@@ -23,11 +23,11 @@ import UIKit
public class SPAnimationUpward {
fileprivate static let durationListAnimation: TimeInterval = 0.45
fileprivate static let coefLenthForTransition: CGFloat = 2.8
fileprivate static let delayPerItem: TimeInterval = 0.09
public static let durationListAnimation: TimeInterval = 0.45
public static let coefLenthForTransition: CGFloat = 2.8
public static let delayPerItem: TimeInterval = 0.09
static func hide(_ duration: TimeInterval,
public static func hide(_ duration: TimeInterval,
view: UIView,
delay: TimeInterval = 0,
withComplection completion: (() -> Void)! = {}) {
@@ -48,7 +48,7 @@ public class SPAnimationUpward {
})
}
static func hideList(_ duration: TimeInterval = durationListAnimation,
public static func hideList(_ duration: TimeInterval = durationListAnimation,
views: [UIView],
delayPerItem: TimeInterval = delayPerItem,
withComplection completion: (() -> Void)! = {}) {
@@ -69,7 +69,7 @@ public class SPAnimationUpward {
}
static func show(_ duration: TimeInterval,
public static func show(_ duration: TimeInterval,
view: UIView,
delay: TimeInterval = 0,
withComplection completion: (() -> Void)! = {}) {
@@ -93,7 +93,7 @@ public class SPAnimationUpward {
})
}
static func showList(_ duration: TimeInterval = durationListAnimation,
public static func showList(_ duration: TimeInterval = durationListAnimation,
views: [UIView],
delayPerItem: TimeInterval = delayPerItem,
options: UIView.AnimationOptions = [],
@@ -24,19 +24,19 @@ import StoreKit
struct SPApp {
static var udid: String? {
public static var udid: String? {
return UIDevice.current.identifierForVendor?.uuidString
}
static var displayName: String? {
public static var displayName: String? {
return Bundle.main.object(forInfoDictionaryKey: "CFBundleDisplayName") as? String
}
static var rootController: UIViewController? {
public static var rootController: UIViewController? {
return UIApplication.shared.keyWindow?.rootViewController
}
static func set(rootController: UIViewController, animatable: Bool = true) {
public static func set(rootController: UIViewController, animatable: Bool = true) {
rootController.view.frame = UIScreen.main.bounds
@@ -57,7 +57,7 @@ struct SPApp {
}
}
static func set(elementsColor: UIColor) {
public static func set(elementsColor: UIColor) {
UINavigationController.elementsColor = elementsColor
UIAlertController.elementsColor = elementsColor
UITabBarController.elementsColor = elementsColor
@@ -25,7 +25,7 @@ extension SPApp {
public struct Badge {
static var number: Int {
public static var number: Int {
get {
return UIApplication.shared.applicationIconBadgeNumber
}
@@ -34,7 +34,7 @@ extension SPApp {
}
}
static func reset() {
public static func reset() {
UIApplication.shared.applicationIconBadgeNumber = 0
}
@@ -23,13 +23,13 @@ import UIKit
extension SPApp {
struct Launch {
public struct Launch {
static func run() {
public static func run() {
self.count += 1
}
static var count: Int {
public static var count: Int {
get {
return UserDefaults.standard.value(forKey: "SPLaunchCount") as? Int ?? 0
}
@@ -38,7 +38,7 @@ extension SPApp {
}
}
static var isFirstLaunch: Bool {
public static var isFirstLaunch: Bool {
return (self.count == 1) || (self.count == 0)
}
@@ -24,7 +24,7 @@ import SafariServices
extension SPApp {
static func open(app: SPSystemApp) {
public static func open(app: SPSystemApp) {
switch app {
case SPSystemApp.photos:
guard let settingsUrl = URL(string: "photos-redirect://") else {
@@ -63,7 +63,7 @@ extension SPApp {
}
}
static func open(link: String, redirect: Bool) {
public static func open(link: String, redirect: Bool) {
guard let url = URL(string: link) else {
print("SPOpener - can not create URL")
@@ -24,11 +24,11 @@ import StoreKit
struct SPAppStore {
static func link(appID: String) -> String {
public static func link(appID: String) -> String {
return "https://itunes.apple.com/by/app/id" + appID
}
static func open(appID: String) {
public static func open(appID: String) {
if let url = URL(string: "itms-apps://itunes.apple.com/app/id\(appID)"),
UIApplication.shared.canOpenURL(url) {
if #available(iOS 10.0, *) {
@@ -39,7 +39,7 @@ struct SPAppStore {
}
}
static func requestReview(appID: String, force: Bool) {
public static func requestReview(appID: String, force: Bool) {
if force {
if let url = URL(string: "itms-apps://itunes.apple.com/us/app/apple-store/id\(appID)?mt=8&action=write-review"),
UIApplication.shared.canOpenURL(url) {
@@ -56,13 +56,13 @@ struct SPAppStore {
}
}
static func requestReview() {
public static func requestReview() {
if #available(iOS 10.3, *) {
SKStoreReviewController.requestReview()
}
}
static func isUpdateAvailable(completion: @escaping (Bool)->()) {
public static func isUpdateAvailable(completion: @escaping (Bool)->()) {
guard let info = Bundle.main.infoDictionary,
let currentVersion = info["CFBundleShortVersionString"] as? String,
@@ -24,7 +24,7 @@ import AVFoundation
public struct SPAudio {
static func notStopBackgroundMusic() {
public static func notStopBackgroundMusic() {
do {
try AVAudioSession.sharedInstance().setCategory(AVAudioSession.Category(rawValue: convertFromAVAudioSessionCategory(AVAudioSession.Category.ambient)), mode: AVAudioSession.Mode.default)
try AVAudioSession.sharedInstance().setActive(true)
@@ -27,7 +27,7 @@ public class SPAudioPlayer: NSObject, AVAudioPlayerDelegate {
fileprivate var player: AVAudioPlayer = AVAudioPlayer()
fileprivate var endPlayingComplection: (()->())? = nil
func play(fileName: String, complection: (()->())? = nil) {
public func play(fileName: String, complection: (()->())? = nil) {
self.endPlayingComplection?()
self.player = AVAudioPlayer()
let url = Bundle.main.url(forResource: fileName, withExtension: nil)
@@ -47,7 +47,7 @@ public class SPAudioPlayer: NSObject, AVAudioPlayerDelegate {
}
}
func stop() {
public func stop() {
player.stop()
}
@@ -23,7 +23,7 @@ import UIKit
struct SPBufer {
static var text: String? {
public static var text: String? {
get {
return UIPasteboard.general.string
}
@@ -21,7 +21,4 @@
import UIKit
struct SPCodeDraw {
private init() {}
}
public struct SPCodeDraw { private init() {} }
@@ -23,7 +23,7 @@ import UIKit
public struct SPConstraints {
static func setEqualSizeSuperview(for view: UIView) {
public static func setEqualSizeSuperview(for view: UIView) {
if let superView = view.superview {
view.translatesAutoresizingMaskIntoConstraints = false
NSLayoutConstraint.activate([
@@ -21,7 +21,7 @@
import Foundation
public func delay(_ delay:Double, closure:@escaping ()->()) {
public func delay(_ delay:Double, closure: @escaping ()->()) {
let when = DispatchTime.now() + delay
DispatchQueue.main.asyncAfter(deadline: when) {
closure()
@@ -21,19 +21,19 @@
import UIKit
struct SPDevice {
public struct SPDevice {
static var iphone: Bool {
public static var iphone: Bool {
return UIDevice.current.userInterfaceIdiom == .phone
}
static var ipad: Bool {
public static var ipad: Bool {
return UIDevice.current.userInterfaceIdiom == .pad
}
struct Orientation {
public struct Orientation {
static var isPortrait: Bool {
public static var isPortrait: Bool {
var isPortraitOrientation = true
if UIDevice.current.orientation.isValidInterfaceOrientation {
if UIDevice.current.orientation.isPortrait {
@@ -23,7 +23,7 @@ import UIKit
struct SPDownloader {
static func image(link: String, withComplection complection: @escaping (UIImage?) -> ()) {
public static func image(link: String, withComplection complection: @escaping (UIImage?) -> ()) {
guard let url = URL(string: link) else {
DispatchQueue.main.async {
complection(nil)
@@ -23,7 +23,7 @@ import Foundation
extension Array {
func get(count: Int) -> Array {
public func get(count: Int) -> Array {
if (count < self.count) { return Array(self[0..<count]) }
return Array(self)
}
@@ -31,7 +31,7 @@ extension Array {
extension Array where Element: Equatable {
mutating func removeDuplicates() {
public mutating func removeDuplicates() {
var result = [Element]()
for value in self {
if result.contains(value) == false { result.append(value) }
@@ -42,7 +42,7 @@ extension Array where Element: Equatable {
extension Array where Element: Hashable {
func after(item: Element) -> Element? {
public func after(item: Element) -> Element? {
if let index = self.index(of: item), index + 1 < self.count { return self[index + 1] }
return nil
}
@@ -23,17 +23,17 @@ import UIKit
extension CGRect {
var bottomXPosition: CGFloat {
public var bottomXPosition: CGFloat {
get { return self.origin.x + self.width }
set { self.origin.x = newValue - self.width }
}
var bottomYPosition: CGFloat {
public var bottomYPosition: CGFloat {
get { return self.origin.y + self.height }
set { self.origin.y = newValue - self.height }
}
var minSideSize: CGFloat {
public var minSideSize: CGFloat {
return min(self.width, self.height)
}
}
@@ -23,13 +23,13 @@ import UIKit
extension CGSize {
func resize(width: CGFloat) -> CGSize {
public func resize(width: CGFloat) -> CGSize {
let relativeSideSize = self.width / self.height
let newHeight = width / relativeSideSize
return CGSize.init(width: width, height: newHeight)
}
func resize(height: CGFloat) -> CGSize {
public func resize(height: CGFloat) -> CGSize {
let relativeSideSize = self.width / self.height
let newWidth = height * relativeSideSize
return CGSize.init(width: newWidth, height: height)
@@ -23,13 +23,13 @@ import Foundation
extension Date {
func format(mask: String) -> String {
public func format(mask: String) -> String {
let dateFormatter = DateFormatter()
dateFormatter.dateFormat = mask
return dateFormatter.string(from: self)
}
static func create(from value: String) -> Date? {
public static func create(from value: String) -> Date? {
let formatter = DateFormatter()
formatter.dateFormat = "dd.MM.yyyy HH:mm"
let date = formatter.date(from: value)
@@ -24,57 +24,57 @@ import UIKit
extension String {
var digits: String {
public var digits: String {
return components(separatedBy: CharacterSet.decimalDigits.inverted).joined()
}
mutating func dropLast(substring: String) {
public mutating func dropLast(substring: String) {
if self.hasSuffix(substring) {
self = String(dropLast(substring.count))
}
}
mutating func dropFirst(substring: String) {
public mutating func dropFirst(substring: String) {
if self.hasPrefix(substring) {
self = String(dropFirst(substring.count))
}
}
func uppercasedFirstLetter() -> String {
public func uppercasedFirstLetter() -> String {
let lowercaseSctring = self.lowercased()
return lowercaseSctring.prefix(1).uppercased() + lowercaseSctring.dropFirst()
}
mutating func uppercaseFirstLetter() {
public mutating func uppercaseFirstLetter() {
self = self.uppercasedFirstLetter()
}
func removeAllSpaces() -> String {
public func removeAllSpaces() -> String {
return self.components(separatedBy: .whitespaces).joined()
}
mutating func removeAllSpaces() {
public mutating func removeAllSpaces() {
self = self.removeAllSpaces()
}
var isEmail: Bool {
public var isEmail: Bool {
let emailRegEx = "[A-Z0-9a-z._%+-]+@[A-Za-z0-9.-]+\\.[A-Za-z]{2,64}"
let emailTest = NSPredicate(format:"SELF MATCHES %@", emailRegEx)
return emailTest.evaluate(with: self)
}
var isLink: Bool {
public var isLink: Bool {
if let url = URL(string: self) {
return UIApplication.shared.canOpenURL(url)
}
return false
}
mutating func replace(_ replacingString: String, with newString: String) {
public mutating func replace(_ replacingString: String, with newString: String) {
self = self.replacingOccurrences(of: replacingString, with: newString)
}
func replace(_ replacingString: String, with newString: String) -> String {
public func replace(_ replacingString: String, with newString: String) -> String {
return self.replacingOccurrences(of: replacingString, with: newString)
}
}
@@ -23,7 +23,7 @@ import UIKit
extension UITextField {
@IBInspectable var placeholderColor: UIColor? {
@IBInspectable public var placeholderColor: UIColor? {
get {
return self.placeholderColor
}
@@ -23,7 +23,7 @@ import UIKit
extension UIAlertController {
static var elementsColor: UIColor {
public static var elementsColor: UIColor {
get {
return UIView.appearance(whenContainedInInstancesOf: [UIAlertController.self]).tintColor
}
@@ -87,17 +87,24 @@ extension UIAlertController {
extension UIAlertController {
func addAction(title: String, complection: @escaping ()->()) {
public func addAction(title: String, complection: @escaping ()->()) {
let action = UIAlertAction(title: title, style: .default) { (action) in
complection()
}
self.addAction(action)
}
func addDestructiveAction(title: String, complection: @escaping ()->()) {
public func addDestructiveAction(title: String, complection: @escaping ()->()) {
let action = UIAlertAction(title: title, style: .destructive) { (action) in
complection()
}
self.addAction(action)
}
public func addCancelAction(title: String, complection: @escaping ()->() = {}) {
let action = UIAlertAction(title: title, style: .cancel) { (action) in
complection()
}
self.addAction(action)
}
}
@@ -23,7 +23,7 @@ import UIKit
extension UIButton {
typealias UIButtonTargetClosure = () -> ()
public typealias UIButtonTargetClosure = () -> ()
private class ClosureWrapper: NSObject {
let closure: UIButtonTargetClosure
@@ -47,7 +47,7 @@ extension UIButton {
}
}
func target(_ action: @escaping UIButtonTargetClosure) {
public func target(_ action: @escaping UIButtonTargetClosure) {
targetClosure = action
addTarget(self, action: #selector(UIButton.targetAction), for: .touchUpInside)
}
@@ -60,20 +60,20 @@ extension UIButton {
extension UIButton {
func setTitle(_ title: String) {
public func setTitle(_ title: String) {
self.setTitle(title, for: .normal)
}
func setTitleColor(_ color: UIColor) {
public func setTitleColor(_ color: UIColor) {
self.setTitleColor(color, for: .normal)
self.setTitleColor(color.withAlphaComponent(0.7), for: .highlighted)
}
func removeAllTargets() {
public func removeAllTargets() {
self.removeTarget(nil, action: nil, for: .allEvents)
}
func showText(_ text: String, withComplection completion: (() -> Void)! = {}) {
public func showText(_ text: String, withComplection completion: (() -> Void)! = {}) {
let baseText = self.titleLabel?.text ?? " "
SPAnimation.animate(0.2, animations: {
self.titleLabel?.alpha = 0
@@ -97,7 +97,7 @@ extension UIButton {
})
}
func setAnimatableText(_ text: String, withComplection completion: (() -> Void)! = {}) {
public func setAnimatableText(_ text: String, withComplection completion: (() -> Void)! = {}) {
SPAnimation.animate(0.3, animations: {
self.titleLabel?.alpha = 0
}, withComplection: {
@@ -110,7 +110,7 @@ extension UIButton {
})
}
func hideContent(completion: (() -> Void)! = {}) {
public func hideContent(completion: (() -> Void)! = {}) {
SPAnimation.animate(0.2, animations: {
self.titleLabel?.alpha = 0
}, withComplection: {
@@ -118,7 +118,7 @@ extension UIButton {
})
}
func showContent(completion: (() -> Void)! = {}) {
public func showContent(completion: (() -> Void)! = {}) {
SPAnimation.animate(0.2, animations: {
self.titleLabel?.alpha = 1
}, withComplection: {
@@ -23,7 +23,7 @@ import UIKit
extension UICollectionView {
var currentIndexCellPath: IndexPath? {
public var currentIndexCellPath: IndexPath? {
let visibleRect = CGRect(origin: self.contentOffset, size: self.bounds.size)
let visiblePoint = CGPoint.init(x: visibleRect.midX, y: visibleRect.midY)
let visibleIndexPath = self.indexPathForItem(at: visiblePoint)
@@ -23,7 +23,7 @@ import UIKit
public extension UIColor {
convenience init(hex: String) {
public convenience init(hex: String) {
var red: CGFloat = 0.0
var green: CGFloat = 0.0
var blue: CGFloat = 0.0
@@ -23,7 +23,7 @@ import UIKit
public extension UILabel {
func setShadowOffsetForLetters(blurRadius: CGFloat = 0, widthOffset: CGFloat = 0, heightOffset: CGFloat, opacity: CGFloat) {
public func setShadowOffsetForLetters(blurRadius: CGFloat = 0, widthOffset: CGFloat = 0, heightOffset: CGFloat, opacity: CGFloat) {
self.layer.shadowRadius = blurRadius
self.layer.shadowOffset = CGSize(
width: widthOffset,
@@ -32,29 +32,29 @@ public extension UILabel {
self.layer.shadowOpacity = Float(opacity)
}
func setShadowOffsetFactorForLetters(blurRadius: CGFloat = 0, widthOffsetFactor: CGFloat = 0, heightOffsetFactor: CGFloat, opacity: CGFloat) {
public func setShadowOffsetFactorForLetters(blurRadius: CGFloat = 0, widthOffsetFactor: CGFloat = 0, heightOffsetFactor: CGFloat, opacity: CGFloat) {
let widthOffset = widthOffsetFactor * self.frame.width
let heightOffset = heightOffsetFactor * self.frame.height
self.setShadowOffsetForLetters(blurRadius: blurRadius, widthOffset: widthOffset, heightOffset: heightOffset, opacity: opacity)
}
func removeShadowForLetters() {
public func removeShadowForLetters() {
self.setShadowOffsetForLetters(blurRadius: 0, widthOffset: 0, heightOffset: 0, opacity: 0)
}
func setCenteringAlignment() {
public func setCenteringAlignment() {
self.textAlignment = .center
self.baselineAdjustment = .alignCenters
}
func setLettersSpacing(_ value: CGFloat) {
public func setLettersSpacing(_ value: CGFloat) {
if let textString = text {
let attrs: [NSAttributedString.Key : Any] = [.kern: value]
attributedText = NSAttributedString(string: textString, attributes: attrs)
}
}
func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
public func setLineSpacing(lineSpacing: CGFloat = 0.0, lineHeightMultiple: CGFloat = 0.0) {
guard let labelText = self.text else { return }
@@ -23,7 +23,7 @@ import UIKit
extension UINavigationController {
static var elementsColor: UIColor {
public static var elementsColor: UIColor {
get {
if UINavigationBar.appearance().tintColor != nil {
return UINavigationBar.appearance().tintColor
@@ -23,7 +23,7 @@ import UIKit
extension UITabBarController {
static var elementsColor: UIColor {
public static var elementsColor: UIColor {
get {
if UITabBar.appearance().tintColor != nil {
return UITabBar.appearance().tintColor
@@ -36,7 +36,7 @@ extension UITabBarController {
}
}
func addTabBarItem(title: String, image: UIImage, selectedImage: UIImage? = nil, controller: UIViewController) {
public func addTabBarItem(title: String, image: UIImage, selectedImage: UIImage? = nil, controller: UIViewController) {
let tabBarItem = UITabBarItem(
title: title,
@@ -23,19 +23,19 @@ import UIKit
extension UITableView {
var isEmpty: Bool {
public var isEmpty: Bool {
return self.lastSectionWithRows == nil
}
func isEmpty(section: Int) -> Bool {
public func isEmpty(section: Int) -> Bool {
return self.numberOfRows(inSection: section) == 0
}
var lastSection: Int {
public var lastSection: Int {
return self.numberOfSections - 1
}
var lastSectionWithRows: Int? {
public var lastSectionWithRows: Int? {
if self.numberOfSections == 0 { return nil }
var section = self.numberOfSections - 1
if section < 0 { return nil }
@@ -46,7 +46,7 @@ extension UITableView {
return nil
}
var firstSectionWithRows: Int? {
public var firstSectionWithRows: Int? {
if self.numberOfSections == 0 { return nil }
var section = 0
if section > self.numberOfSections - 1 { return nil }
@@ -27,7 +27,7 @@ extension UITableViewCell {
return subviews.compactMap { $0 as? UIButton }.first
}
var highlightedColor: UIColor? {
public var highlightedColor: UIColor? {
get {
return self.backgroundView?.backgroundColor
}
@@ -23,7 +23,7 @@ import UIKit
extension UITextField {
var isEmptyText: Bool {
public var isEmptyText: Bool {
get {
if self.text == "" {
return true
@@ -24,11 +24,11 @@ import Photos
extension UIViewController {
func present(_ viewControllerToPresent: UIViewController, completion: (() -> Swift.Void)? = nil) {
public func present(_ viewControllerToPresent: UIViewController, completion: (() -> Swift.Void)? = nil) {
self.present(viewControllerToPresent, animated: true, completion: completion)
}
@objc func dismiss() {
@objc public func dismiss() {
self.dismiss(animated: true, completion: nil)
}
@@ -41,20 +41,20 @@ extension UIViewController {
extension UIViewController {
func dismissKeyboardWhenTappedAround() {
public func dismissKeyboardWhenTappedAround() {
let tap: UITapGestureRecognizer = UITapGestureRecognizer(target: self, action: #selector(UIViewController.dismissKeyboard))
tap.cancelsTouchesInView = false
view.addGestureRecognizer(tap)
}
@objc func dismissKeyboard() {
@objc public func dismissKeyboard() {
view.endEditing(true)
}
}
extension UIViewController {
func save(image: UIImage) {
public func save(image: UIImage) {
if PHPhotoLibrary.authorizationStatus() == PHAuthorizationStatus.authorized {
UIImageWriteToSavedPhotosAlbum(image, self, #selector(self.image(_:didFinishSavingWithError:contextInfo:)), nil)
} else {
@@ -62,7 +62,7 @@ extension UIViewController {
}
}
func saveVideo(url: String, complection: @escaping (Bool)->()) {
public func saveVideo(url: String, complection: @escaping (Bool)->()) {
DispatchQueue.global(qos: .utility).async {
let urls = URL(string: url)
let urldata = try? Data(contentsOf: urls!)
@@ -90,7 +90,7 @@ extension UIViewController {
}
}
@objc func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
@objc public func image(_ image: UIImage, didFinishSavingWithError error: Error?, contextInfo: UnsafeRawPointer) {
if let _ = error {
self.imageSaved(isSuccses: false)
} else {
@@ -98,14 +98,14 @@ extension UIViewController {
}
}
@objc func imageSaved(isSuccses: Bool) {
@objc public func imageSaved(isSuccses: Bool) {
fatalError("SPUIViewControllerExtenshion - Need ovveride 'imageSaved' func")
}
}
extension UIViewController {
func setPrefersLargeNavigationTitle(_ title: String, smallScreenToSmallBar: Bool = true) {
public func setPrefersLargeNavigationTitle(_ title: String, smallScreenToSmallBar: Bool = true) {
self.navigationItem.title = title
if #available(iOS 11.0, *) {
self.navigationItem.largeTitleDisplayMode = .automatic
@@ -141,7 +141,7 @@ extension UIViewController {
extension UIViewController {
var safeArea: UIEdgeInsets {
public var safeArea: UIEdgeInsets {
if #available(iOS 11.0, *) {
return self.view.safeAreaInsets
} else {
@@ -149,18 +149,18 @@ extension UIViewController {
}
}
var navigationBarHeight: CGFloat {
public var navigationBarHeight: CGFloat {
return self.navigationController?.navigationBar.frame.height ?? 0
}
static var statusBarHeight: CGFloat {
public static var statusBarHeight: CGFloat {
return UIApplication.shared.statusBarFrame.height
}
}
extension UIViewController {
var navigationTitleColor: UIColor? {
public var navigationTitleColor: UIColor? {
get {
return (self.navigationController?.navigationBar.titleTextAttributes?[NSAttributedString.Key.foregroundColor] as? UIColor) ?? nil
}
@@ -23,7 +23,7 @@ import UIKit
public extension UIView {
var viewController: UIViewController? {
public var viewController: UIViewController? {
get {
if let nextResponder = self.next as? UIViewController { return nextResponder }
else if let nextResponder = self.next as? UIView { return nextResponder.viewController }
@@ -34,7 +34,7 @@ public extension UIView {
public extension UIView {
var safeArea: UIEdgeInsets {
public var safeArea: UIEdgeInsets {
if #available(iOS 11.0, *) {
return self.safeAreaInsets
} else{
@@ -42,24 +42,24 @@ public extension UIView {
}
}
func set(width: CGFloat, height: CGFloat) {
public func set(width: CGFloat, height: CGFloat) {
self.setHeight(height)
self.setWidth(width)
}
func setHeight(_ height: CGFloat) {
public func setHeight(_ height: CGFloat) {
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: self.frame.width, height: height)
}
func setWidth(_ width: CGFloat) {
public func setWidth(_ width: CGFloat) {
self.frame = CGRect.init(x: self.frame.origin.x, y: self.frame.origin.y, width: width, height: self.frame.height)
}
func setEqualsFrameFromBounds(_ view: UIView, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
public func setEqualsFrameFromBounds(_ view: UIView, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
self.setEqualsFrameFromBounds(view.bounds, withWidthFactor: widthFactor, maxWidth: maxWidth, withHeightFactor: heightFactor, maxHeight: maxHeight, withCentering: withCentering)
}
func setEqualsFrameFromBounds(_ bounds: CGRect, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
public func setEqualsFrameFromBounds(_ bounds: CGRect, withWidthFactor widthFactor: CGFloat = 1, maxWidth: CGFloat? = nil, withHeightFactor heightFactor: CGFloat = 1, maxHeight: CGFloat? = nil, withCentering: Bool = false) {
var width = bounds.width * widthFactor
if maxWidth != nil { width.setIfMore(when: maxWidth!) }
@@ -75,7 +75,7 @@ public extension UIView {
}
}
func setEqualsBoundsFromSuperview(customWidth: CGFloat? = nil, customHeight: CGFloat? = nil) {
public func setEqualsBoundsFromSuperview(customWidth: CGFloat? = nil, customHeight: CGFloat? = nil) {
if self.superview == nil { return }
self.frame = CGRect.init(origin: CGPoint.zero, size: self.superview!.frame.size)
if customWidth != nil {
@@ -86,7 +86,7 @@ public extension UIView {
}
}
func resize(width: CGFloat) {
public func resize(width: CGFloat) {
let relativeFactor = self.frame.width / self.frame.height
if relativeFactor.isNaN { return }
self.frame = CGRect.init(
@@ -97,7 +97,7 @@ public extension UIView {
)
}
func resize(height: CGFloat) {
public func resize(height: CGFloat) {
let relativeFactor = self.frame.width / self.frame.height
if relativeFactor.isNaN { return }
self.frame = CGRect.init(
@@ -108,27 +108,27 @@ public extension UIView {
)
}
func setYCenteringFromSuperview() {
public func setYCenteringFromSuperview() {
self.center.y = (self.superview?.frame.height ?? 0) / 2
}
func setXCenteringFromSuperview() {
public func setXCenteringFromSuperview() {
self.center.x = (self.superview?.frame.width ?? 0) / 2
}
func setToCenterInSuperview() {
public func setToCenterInSuperview() {
self.center = CGPoint.init(x: ((self.superview?.frame.width) ?? 0) / 2, y: ((self.superview?.frame.height) ?? 0) / 2)
}
}
public extension UIView {
func setParalax(amountFactor: CGFloat) {
public func setParalax(amountFactor: CGFloat) {
let amount = self.frame.minSideSize * amountFactor
self.setParalax(amount: amount)
}
func setParalax(amount: CGFloat) {
public func setParalax(amount: CGFloat) {
self.motionEffects.removeAll()
let horizontal = UIInterpolatingMotionEffect(keyPath: "center.x", type: .tiltAlongHorizontalAxis)
horizontal.minimumRelativeValue = -amount
@@ -146,7 +146,7 @@ public extension UIView {
public extension UIView {
func addGrade(alpha: CGFloat, color: UIColor = UIColor.black) -> UIView {
public func addGrade(alpha: CGFloat, color: UIColor = UIColor.black) -> UIView {
let gradeView = UIView.init()
gradeView.alpha = 0
self.addSubview(gradeView)
@@ -159,7 +159,7 @@ public extension UIView {
extension UIView {
func setShadow(
public func setShadow(
xTranslationFactor: CGFloat,
yTranslationFactor: CGFloat,
widthRelativeFactor: CGFloat,
@@ -191,7 +191,7 @@ extension UIView {
self.layer.shadowPath = shadowPath.cgPath;
}
func setShadow(
public func setShadow(
xTranslation: CGFloat,
yTranslation: CGFloat,
widthRelativeFactor: CGFloat,
@@ -216,14 +216,14 @@ extension UIView {
self.layer.shadowPath = shadowPath.cgPath
}
func removeShadow() {
public func removeShadow() {
self.layer.shadowColor = nil
self.layer.shadowOffset = CGSize.zero
self.layer.shadowOpacity = 0
self.layer.shadowPath = nil
}
func addShadowOpacityAnimation(to: CGFloat, duration: CFTimeInterval) {
public func addShadowOpacityAnimation(to: CGFloat, duration: CFTimeInterval) {
let animation = CABasicAnimation(keyPath:"shadowOpacity")
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
animation.fromValue = self.layer.cornerRadius
@@ -237,7 +237,7 @@ extension UIView {
extension UIView {
func addCornerRadiusAnimation(to: CGFloat, duration: CFTimeInterval) {
public func addCornerRadiusAnimation(to: CGFloat, duration: CFTimeInterval) {
let animation = CABasicAnimation(keyPath:"cornerRadius")
animation.timingFunction = CAMediaTimingFunction(name: CAMediaTimingFunctionName.easeOut)
animation.fromValue = self.layer.cornerRadius
@@ -247,14 +247,14 @@ extension UIView {
self.layer.cornerRadius = to
}
func show(duration: TimeInterval = 0.3) {
public func show(duration: TimeInterval = 0.3) {
self.isHidden = false
SPAnimation.animate(duration, animations: {
self.alpha = 1
})
}
func hide(duration: TimeInterval = 0.3) {
public func hide(duration: TimeInterval = 0.3) {
SPAnimation.animate(duration, animations: {
self.alpha = 0
}, withComplection: {
@@ -262,21 +262,21 @@ extension UIView {
})
}
func removeAllAnimations() {
public func removeAllAnimations() {
self.layer.removeAllAnimations()
}
}
extension UIView {
func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
public func roundCorners(_ corners: UIRectCorner, radius: CGFloat) {
let path = UIBezierPath(roundedRect: self.bounds, byRoundingCorners: corners, cornerRadii: CGSize(width: radius, height: radius))
let mask = CAShapeLayer()
mask.path = path.cgPath
self.layer.mask = mask
}
func round() {
public func round() {
self.layer.cornerRadius = self.frame.minSideSize / 2
}
}
@@ -23,12 +23,12 @@ import UIKit
extension UIVisualEffectView {
convenience init(style: UIBlurEffect.Style) {
public convenience init(style: UIBlurEffect.Style) {
let effect = UIBlurEffect(style: style)
self.init(effect: effect)
}
convenience init(vibrancy style: UIBlurEffect.Style) {
public convenience init(vibrancy style: UIBlurEffect.Style) {
let effect = UIBlurEffect(style: style)
let vibrancyEffect = UIVibrancyEffect(blurEffect: effect)
self.init(effect: vibrancyEffect)
@@ -23,15 +23,15 @@ import Foundation
extension UserDefaults {
func set(stringArray array: [String], forKey key: String) {
public func set(stringArray array: [String], forKey key: String) {
self.set(array, forKey: key)
}
func set(boolArray array: [Bool], forKey key: String) {
public func set(boolArray array: [Bool], forKey key: String) {
self.set(array, forKey: key)
}
func boolArray(forKey defaultName: String) -> [Bool] {
public func boolArray(forKey defaultName: String) -> [Bool] {
return UserDefaults.standard.array(forKey: defaultName) as? [Bool] ?? []
}
}
@@ -21,9 +21,9 @@
import UIKit
struct SPLayout {
public struct SPLayout {
static func sizeWith(widthFactor: CGFloat, maxWidth: CGFloat?, heightFactor: CGFloat, maxHeight: CGFloat?, relativeSideFactor: CGFloat?, from size: CGSize) -> CGSize {
public static func sizeWith(widthFactor: CGFloat, maxWidth: CGFloat?, heightFactor: CGFloat, maxHeight: CGFloat?, relativeSideFactor: CGFloat?, from size: CGSize) -> CGSize {
var widthArea = size.width * widthFactor
var heightArea = size.height * heightFactor
@@ -24,7 +24,7 @@ import LocalAuthentication
struct SPLocalAuthentication {
static var isEnable: Bool {
public static var isEnable: Bool {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
@@ -38,7 +38,7 @@ struct SPLocalAuthentication {
}
}
static func request(reason: String, complecton: @escaping (Bool)->()) {
public static func request(reason: String, complecton: @escaping (Bool)->()) {
let context = LAContext()
var error: NSError?
if context.canEvaluatePolicy(.deviceOwnerAuthenticationWithBiometrics, error: &error) {
@@ -21,7 +21,7 @@
import UIKit
enum SPLocale: String, CaseIterable {
public enum SPLocale: String, CaseIterable {
case ru = "ru"
case en = "en"
@@ -24,11 +24,11 @@ import MessageUI
struct SPMail {
static var canSendEmail: Bool {
public static var canSendEmail: Bool {
return MFMailComposeViewController.canSendMail()
}
static func openApp(to email: String, subject: String? = nil, body: String? = nil) {
public static func openApp(to email: String, subject: String? = nil, body: String? = nil) {
let parametrs = "mailto:\(email)?subject=\(subject ?? "")&body=\(body ?? "")".addingPercentEncoding(withAllowedCharacters: CharacterSet.urlQueryAllowed)
if parametrs != nil {
@@ -40,7 +40,7 @@ struct SPMail {
}
}
static func dialog(to email: String, subject: String? = nil, body: String? = nil, on viewController: UIViewController) {
public static func dialog(to email: String, subject: String? = nil, body: String? = nil, on viewController: UIViewController) {
let mailVC = MFMailComposeViewController()
mailVC.mailComposeDelegate = SPMailSingltone.sharedInstance
@@ -21,21 +21,21 @@
import UIKit
enum SPNativeColors {
public enum SPNativeColors {
static let red = UIColor.init(hex: "FF3B30")
static let orange = UIColor.init(hex: "FF9500")
static let yellow = UIColor.init(hex: "FFCC00")
static let green = UIColor.init(hex: "4CD964")
static let tealBlue = UIColor.init(hex: "5AC8FA")
static let blue = UIColor.init(hex: "007AFF")
static let purple = UIColor.init(hex: "5856D6")
static let pink = UIColor.init(hex: "FF2D55")
static let white = UIColor.init(hex: "FFFFFF")
static let customGray = UIColor.init(hex: "EFEFF4")
static let lightGray = UIColor.init(hex: "E5E5EA")
static let lightGray2 = UIColor.init(hex: "D1D1D6")
static let midGray = UIColor.init(hex: "C7C7CC")
static let gray = UIColor.init(hex: "8E8E93")
static let black = UIColor.init(hex: "000000")
public static let red = UIColor.init(hex: "FF3B30")
public static let orange = UIColor.init(hex: "FF9500")
public static let yellow = UIColor.init(hex: "FFCC00")
public static let green = UIColor.init(hex: "4CD964")
public static let tealBlue = UIColor.init(hex: "5AC8FA")
public static let blue = UIColor.init(hex: "007AFF")
public static let purple = UIColor.init(hex: "5856D6")
public static let pink = UIColor.init(hex: "FF2D55")
public static let white = UIColor.init(hex: "FFFFFF")
public static let customGray = UIColor.init(hex: "EFEFF4")
public static let lightGray = UIColor.init(hex: "E5E5EA")
public static let lightGray2 = UIColor.init(hex: "D1D1D6")
public static let midGray = UIColor.init(hex: "C7C7CC")
public static let gray = UIColor.init(hex: "8E8E93")
public static let black = UIColor.init(hex: "000000")
}
@@ -22,9 +22,9 @@
import UIKit
import UserNotifications
struct SPLocalNotification {
public struct SPLocalNotification {
static func add(from timeInterval: TimeInterval, body: String, title: String? = nil, identifier: String? = nil) {
public static func add(from timeInterval: TimeInterval, body: String, title: String? = nil, identifier: String? = nil) {
let content = UNMutableNotificationContent()
content.body = body
@@ -50,8 +50,8 @@ struct SPLocalNotification {
}
}
static func add(in date: Date, body: String, title: String? = nil, identifier: String? = nil) {
public static func add(in date: Date, body: String, title: String? = nil, identifier: String? = nil) {
let content = UNMutableNotificationContent()
content.body = body
content.title = title ?? ""
@@ -77,7 +77,7 @@ struct SPLocalNotification {
}
}
static func remove(identifier: String) {
public static func remove(identifier: String) {
let center = UNUserNotificationCenter.current()
center.removePendingNotificationRequests(withIdentifiers: [identifier])
}
@@ -22,6 +22,7 @@
import UIKit
public extension String {
public static func random(count: Int) -> String {
let strings = [
"В доме кардинала от меня не было тайн; не раз видел я, как он усердно перелистывает старинные книги и жадно роется в пыли фамильных рукописей. Когда я как-то упрекнул его за бесполезные бессонные ночи, после которых он впадал в болезненное уныние, он взглянул на меня с горькой улыбкой и раскрыл передо мною историю города Рима. В этой книге, в двадцатой главе жизнеописания папы Александра Шестого, я прочел следующие строки, навсегда оставшиеся в моей памяти",
@@ -34,6 +35,7 @@ public extension String {
}
public extension Int {
public static func random(_ n: Int) -> Int {
return Int(arc4random_uniform(UInt32(n)))
}
@@ -44,6 +46,7 @@ public extension Int {
}
public extension Double {
public static func random() -> Double {
return Double(arc4random()) / 0xFFFFFFFF
}
@@ -54,6 +57,7 @@ public extension Double {
}
public extension Float {
public static func random() -> Float {
return Float(arc4random()) / 0xFFFFFFFF
}
@@ -64,6 +68,7 @@ public extension Float {
}
public extension CGFloat {
public static func random() -> CGFloat {
return CGFloat(Float(arc4random()) / 0xFFFFFFFF)
}
@@ -75,7 +80,7 @@ public extension CGFloat {
public extension Collection {
func shuffle() -> [Iterator.Element] {
public func shuffle() -> [Iterator.Element] {
var list = Array(self)
list.shuffleInPlace()
return list
@@ -84,7 +89,7 @@ public extension Collection {
extension Collection where Index == Int {
func random() -> Iterator.Element? {
public func random() -> Iterator.Element? {
return isEmpty ? nil : self[Int(arc4random_uniform(UInt32(endIndex)))]
}
}
@@ -21,4 +21,4 @@
import Foundation
struct SPShadow { private init() {} }
public struct SPShadow { private init() {} }
@@ -23,7 +23,7 @@ import UIKit
extension SPShadow {
struct DeepStyle {
public struct DeepStyle {
private init() {}
@@ -85,14 +85,14 @@ extension SPShadow {
extension UIView {
func setDeepShadow() {
public func setDeepShadow() {
SPShadow.DeepStyle.setFor(view: self)
}
}
extension UILabel {
func setDeepShadowForLetters() {
public func setDeepShadowForLetters() {
SPShadow.DeepStyle.setFor(label: self)
}
}
@@ -25,7 +25,7 @@ public struct SPShare {
public struct Native {
static func share(text: String? = nil, fileNames: [String] = [], images: [UIImage] = [], complection: ((_ isSharing: Bool)->())? = nil, sourceView: UIView, on viewController: UIViewController) {
public static func share(text: String? = nil, fileNames: [String] = [], images: [UIImage] = [], complection: ((_ isSharing: Bool)->())? = nil, sourceView: UIView, on viewController: UIViewController) {
var shareData: [Any] = []
if text != nil {
@@ -21,13 +21,13 @@
import UIKit
class SPInstagram {
public class SPInstagram {
static var isSetApp: Bool {
public static var isSetApp: Bool {
return UIApplication.shared.canOpenURL(URL(string: "instagram://user?username=test")!)
}
static func openPost(id: String) {
public static func openPost(id: String) {
let instagramHooks = "instagram://media?id=\(id)"
let instagramUrl = URL(string: instagramHooks)
let safariURL = URL(string: "instagram.com/\(id)")!
@@ -38,7 +38,7 @@ class SPInstagram {
}
}
static func openUser(username: String) {
public static func openUser(username: String) {
let instagramHooks = "instagram://user?username=\(username)"
let instagramUrl = URL(string: instagramHooks)
let safariURL = URL(string: "https://instagram.com/\(username)")!
@@ -21,13 +21,13 @@
import UIKit
class SPTelegram {
public class SPTelegram {
static var isSetApp: Bool {
public static var isSetApp: Bool {
return UIApplication.shared.canOpenURL(URL(string: "tg://msg?text=test")!)
}
static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
public static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
let urlStringEncoded = text.addingPercentEncoding( withAllowedCharacters: .urlHostAllowed)
let urlOptional = URL(string: "tg://msg?text=\(urlStringEncoded ?? "")")
if let url = urlOptional {
@@ -41,12 +41,12 @@ class SPTelegram {
}
}
static func joinChannel(id: String) {
public static func joinChannel(id: String) {
let url = "https://t.me/joinchat/\(id)"
SPApp.open(link: url, redirect: true)
}
static func openBot(username: String) {
public static func openBot(username: String) {
var username = username
if username.first == "@" {
username.removeFirst()
@@ -21,13 +21,13 @@
import UIKit
class SPTwitter {
public class SPTwitter {
static var isSetApp: Bool {
public static var isSetApp: Bool {
return UIApplication.shared.canOpenURL(URL(string: "twitter://post?message=test")!)
}
static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
public static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
let urlStringEncoded = text.addingPercentEncoding( withAllowedCharacters: .urlHostAllowed)
let urlOptional = URL(string: "twitter://post?message=\(urlStringEncoded ?? "")")
if let url = urlOptional {
@@ -21,13 +21,13 @@
import UIKit
class SPViber {
public class SPViber {
static var isSetApp: Bool {
public static var isSetApp: Bool {
return UIApplication.shared.canOpenURL(URL(string: "viber://forward?text=test")!)
}
static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
public static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
let urlStringEncoded = text.addingPercentEncoding( withAllowedCharacters: .urlHostAllowed)
let urlOptional = URL(string: "viber://forward?text=\(urlStringEncoded ?? "")")
if let url = urlOptional {
@@ -21,13 +21,13 @@
import UIKit
class SPWhatsApp {
public class SPWhatsApp {
static var isSetApp: Bool {
public static var isSetApp: Bool {
return UIApplication.shared.canOpenURL(URL(string: "whatsapp://send?text=test")!)
}
static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
public static func share(text: String, complection: @escaping (_ isOpened: Bool)->() = {_ in }) {
let urlStringEncoded = text.addingPercentEncoding( withAllowedCharacters: .urlHostAllowed)
let urlOptional = URL(string: "whatsapp://send?text=\(urlStringEncoded ?? "")")
if let url = urlOptional {
@@ -1,62 +0,0 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// 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 Foundation
import CoreSpotlight
import MobileCoreServices
struct SPSpotlight {
static let domainIdentifier = "by.ivanvorobei"
static func addItem(identifier: String, title: String, description: String, addedData: Date? = nil, keywords: [String] = []) {
if #available(iOS 9.0, *) {
let attributeSet = CSSearchableItemAttributeSet(itemContentType: kUTTypeMessage as String)
attributeSet.title = title
attributeSet.contentDescription = description
attributeSet.keywords = keywords
if addedData != nil {
attributeSet.contentCreationDate = addedData!
}
let item = CSSearchableItem(uniqueIdentifier: "\(identifier)", domainIdentifier: SPSpotlight.domainIdentifier, attributeSet: attributeSet)
CSSearchableIndex.default().indexSearchableItems([item]) { error in
if let error = error {
print("SPSpotlight addItem error: \(error.localizedDescription)")
}
}
}
}
static func removeItem(identifier: String) {
if #available(iOS 9.0, *) {
CSSearchableIndex.default().deleteSearchableItems(withIdentifiers: ["\(identifier)"]) { error in
if let error = error {
print("SPSpotlight removeItem error: \(error.localizedDescription)")
}
}
}
}
private init() {}
}
@@ -21,7 +21,7 @@
import UIKit
class SPAppStoreActionButton: SPDownloadingButton {
public class SPAppStoreActionButton: SPDownloadingButton {
var style: Style = .base {
didSet {
@@ -78,7 +78,7 @@ class SPAppStoreActionButton: SPDownloadingButton {
self.layer.masksToBounds = true
}
override func setTitle(_ title: String?, for state: UIControl.State) {
override public func setTitle(_ title: String?, for state: UIControl.State) {
switch self.style {
case .base:
super.setTitle(title?.uppercased(), for: state)
@@ -91,7 +91,7 @@ class SPAppStoreActionButton: SPDownloadingButton {
}
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
if self.style == .buyInStore {
self.layer.cornerRadius = 12
@@ -21,7 +21,7 @@
import UIKit
class SPAppleMusicButton: SPButton {
public class SPAppleMusicButton: SPButton {
var type: SPSelectionType = .unselect {
didSet {
@@ -21,7 +21,7 @@
import UIKit
class SPAppleMusicSectionButtonsView: SPView {
public class SPAppleMusicSectionButtonsView: SPView {
let topSeparatorView = SPSeparatorView()
let bottomSeparatorView = SPSeparatorView()
@@ -68,7 +68,7 @@ class SPAppleMusicSectionButtonsView: SPView {
self.layoutSubviews()
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.topSeparatorView.frame.origin = .zero
@@ -21,7 +21,7 @@
import UIKit
class SPDotButton: SPButton {
public class SPDotButton: SPButton {
var customSideSize: CGFloat = 26 {
didSet {
@@ -37,7 +37,7 @@ class SPDotButton: SPButton {
}
}
override var isHighlighted: Bool{
override public var isHighlighted: Bool{
didSet{
if isHighlighted{
UIView.animate(withDuration: 0.1, delay: 0.0, usingSpringWithDamping: 1, initialSpringVelocity: 1.0, options: [.curveEaseOut, .beginFromCurrentState], animations: {
@@ -69,14 +69,14 @@ class SPDotButton: SPButton {
}
}
override func sizeToFit() {
override public func sizeToFit() {
super.sizeToFit()
self.setWidth(self.customSideSize)
self.setHeight(self.customSideSize)
self.layoutSubviews()
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
let space: CGFloat = 2
@@ -21,12 +21,11 @@
import UIKit
class SPDownloadingButton: SPButton {
public class SPDownloadingButton: SPButton {
let activityIndicatorView = UIActivityIndicatorView.init()
var isFrameRounded: Bool = false
func startLoading() {
public func startLoading() {
self.activityIndicatorView.alpha = 0
self.activityIndicatorView.isHidden = false
self.activityIndicatorView.startAnimating()
@@ -39,7 +38,10 @@ class SPDownloadingButton: SPButton {
})
}
func stopLoading() {
public func stopLoading(newText: String? = nil) {
if let newText = newText {
self.setTitle(newText)
}
SPAnimation.animate(0.2, animations: {
self.activityIndicatorView.alpha = 0
}, withComplection: {
@@ -50,13 +52,9 @@ class SPDownloadingButton: SPButton {
})
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.activityIndicatorView.center = CGPoint.init(x: self.frame.width / 2, y: self.frame.height / 2)
if self.isFrameRounded {
self.round()
}
}
}
@@ -21,9 +21,9 @@
import UIKit
class SPNativeLargeButton: SPDownloadingButton {
public class SPNativeLargeButton: SPDownloadingButton {
override var isHighlighted: Bool {
override public var isHighlighted: Bool {
didSet {
if self.gradientView == nil {
if isHighlighted {
@@ -42,7 +42,7 @@ class SPNativeLargeButton: SPDownloadingButton {
}
}
override func commonInit() {
override public func commonInit() {
super.commonInit()
self.titleLabel?.font = UIFont.system(type: UIFont.BoldType.DemiBold, size: 16)
self.setTitleColor(UIColor.white)
@@ -52,7 +52,7 @@ class SPNativeLargeButton: SPDownloadingButton {
self.contentEdgeInsets = UIEdgeInsets.init(top: 15, left: 15, bottom: 15, right: 15)
}
override func sizeToFit() {
override public func sizeToFit() {
super.sizeToFit()
if let superview = self.superview {
let sideSpace: CGFloat = superview.frame.width * 0.112
@@ -62,7 +62,7 @@ class SPNativeLargeButton: SPDownloadingButton {
}
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.gradientView?.setEqualsBoundsFromSuperview()
self.gradientView?.layer.cornerRadius = self.layer.cornerRadius
@@ -21,7 +21,7 @@
import UIKit
class SPPlayCircleButton: UIButton {
public class SPPlayCircleButton: UIButton {
var audioState: AudioState = AudioState.play {
didSet {
@@ -60,7 +60,7 @@ class SPPlayCircleButton: UIButton {
fatalError("init(coder:) has not been implemented")
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: 0.45, withHeightFactor: 0.45, withCentering: true)
self.round()
@@ -21,7 +21,7 @@
import UIKit
class SPSocialButton: UIButton {
public class SPSocialButton: UIButton {
let iconView = SPSocialIconView.init()
var widthIconFactor: CGFloat = 0.5
@@ -33,7 +33,7 @@ class SPSocialButton: UIButton {
}
}
override var isHighlighted: Bool {
override public var isHighlighted: Bool {
didSet {
if isHighlighted {
self.iconView.color = self.iconView.color.withAlphaComponent(0.7)
@@ -43,7 +43,7 @@ class SPSocialButton: UIButton {
}
}
override var isEnabled: Bool {
override public var isEnabled: Bool {
didSet {
if isEnabled {
self.alpha = 1
@@ -79,7 +79,7 @@ class SPSocialButton: UIButton {
self.iconView.color = SPNativeColors.white
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
self.round()
@@ -21,7 +21,7 @@
import UIKit
class SPSystemIconButton: UIButton {
public class SPSystemIconButton: UIButton {
let iconView = SPSystemIconView.init()
var widthIconFactor: CGFloat = 1
@@ -39,7 +39,7 @@ class SPSystemIconButton: UIButton {
}
}
override var isHighlighted: Bool {
override public var isHighlighted: Bool {
didSet {
if isHighlighted {
self.iconView.color = self.color.withAlphaComponent(0.7)
@@ -72,7 +72,7 @@ class SPSystemIconButton: UIButton {
self.addSubview(self.iconView)
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.iconView.setEqualsFrameFromBounds(self, withWidthFactor: self.widthIconFactor, withHeightFactor: self.heightIconFactor, withCentering: true)
}
@@ -103,6 +103,9 @@ class SPGolubevIconView: UIView {
case .headphones:
SPCodeDraw.GolubevIconPack.drawHeadphones(frame: rect, resizing: .aspectFit, white: self.whiteColor, light: self.lightColor, medium: self.mediumColor, dark: self.darkColor)
break
case .windmill:
SPCodeDraw.GolubevIconPack.drawWindmill(frame: rect, resizing: .aspectFit, white: self.whiteColor, light: self.lightColor, medium: self.mediumColor, dark: self.darkColor)
break
}
}
@@ -116,6 +119,7 @@ class SPGolubevIconView: UIView {
case documents
case compass
case headphones
case windmill
}
}
@@ -21,7 +21,7 @@
import UIKit
class SPMengTransformCollectionViewCell: SPCollectionViewCell {
public class SPMengTransformCollectionViewCell: SPCollectionViewCell {
let backgroundImageView = SPDownloadingImageView()
let titleLabel = UILabel()
@@ -86,8 +86,8 @@ class SPMengTransformCollectionViewCell: SPCollectionViewCell {
self.backgroundImageView.bottomAnchor.constraint(equalTo:
contentView.bottomAnchor, constant: 0).isActive = true
self.gradientView.startColorPosition = .TopLeft
self.gradientView.endColorPosition = .BottomRight
self.gradientView.startColorPosition = .topLeft
self.gradientView.endColorPosition = .bottomRight
self.gradientView.isHidden = true
self.gradientView.translatesAutoresizingMaskIntoConstraints = false
self.gradientView.layer.masksToBounds = false
@@ -153,7 +153,7 @@ class SPMengTransformCollectionViewCell: SPCollectionViewCell {
contentView.bottomAnchor, constant: -20).isActive = true
}
override func prepareForReuse() {
override public func prepareForReuse() {
super.prepareForReuse()
self.backgroundImageView.image = nil
self.titleLabel.text = ""
@@ -23,7 +23,7 @@ import UIKit
public class SPCollectionView: UICollectionView {
var layout = SPCollectionViewLayout()
let layout = UICollectionViewFlowLayout()
private var cacheImages: [(link: String, image: UIImage)] = []
required public init?(coder aDecoder: NSCoder) {
@@ -31,29 +31,31 @@ public class SPCollectionView: UICollectionView {
commonInit()
}
init(frame: CGRect) {
super.init(frame: frame, collectionViewLayout: self.layout)
commonInit()
init() {
super.init(frame: .zero, collectionViewLayout: self.layout)
self.commonInit()
}
init() {
super.init(frame: CGRect.zero, collectionViewLayout: self.layout)
commonInit()
public override init(frame: CGRect, collectionViewLayout layout: UICollectionViewLayout) {
super.init(frame: frame, collectionViewLayout: self.layout)
self.commonInit()
}
internal func commonInit() {
self.layout.scrollDirection = .vertical
self.backgroundColor = UIColor.clear
self.collectionViewLayout = self.layout
self.decelerationRate = UIScrollView.DecelerationRate.fast
self.delaysContentTouches = false
self.isPagingEnabled = false
self.showsHorizontalScrollIndicator = false
self.showsVerticalScrollIndicator = false
}
func height(rows: Int) -> CGFloat {
return self.layout.itemSize.height * CGFloat(rows) + self.layout.minimumLineSpacing * CGFloat(rows - 1)
}
}
//MARK: - cache
//MARK: - Cache
extension SPCollectionView {
func setCachedImage(link: String, indexPath: IndexPath, on imageView: SPDownloadingImageView, cell: SPCollectionViewCell) {
@@ -21,7 +21,7 @@
import UIKit
struct SPMengTransformCollectionData {
public struct SPMengTransformCollectionData {
var title: String
var subtitle: String
@@ -40,7 +40,7 @@ struct SPMengTransformCollectionData {
}
}
class SPMengTransformCollectionView: SPCollectionView {
public class SPMengTransformCollectionView: SPPageCollectionView {
var data: [SPMengTransformCollectionData] = []
var withParalax: Bool = true
@@ -73,11 +73,11 @@ class SPMengTransformCollectionView: SPCollectionView {
extension SPMengTransformCollectionView: UICollectionViewDataSource {
func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
public func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
return self.data.count
}
func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
public func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
let data = self.data[indexPath.row]
let cell = collectionView.dequeueReusableCell(withReuseIdentifier: "sectionCell", for: indexPath) as! SPMengTransformCollectionViewCell
cell.currentIndexPath = indexPath
@@ -166,7 +166,7 @@ extension SPMengTransformCollectionView: UICollectionViewDataSource {
extension SPMengTransformCollectionView: UICollectionViewDelegate {
func scrollViewDidScroll(_ scrollView: UIScrollView) {
public func scrollViewDidScroll(_ scrollView: UIScrollView) {
self.updateCells()
}
@@ -0,0 +1,92 @@
// The MIT License (MIT)
// Copyright © 2017 Ivan Vorobei (hello@ivanvorobei.by)
//
// 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
public class SPPageCollectionView: UICollectionView {
var layout = SPCollectionViewLayout()
private var cacheImages: [(link: String, image: UIImage)] = []
required public init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
commonInit()
}
init(frame: CGRect) {
super.init(frame: frame, collectionViewLayout: self.layout)
commonInit()
}
init() {
super.init(frame: CGRect.zero, collectionViewLayout: self.layout)
commonInit()
}
internal func commonInit() {
self.layout.scrollDirection = .vertical
self.backgroundColor = UIColor.clear
self.collectionViewLayout = self.layout
self.decelerationRate = UIScrollView.DecelerationRate.fast
self.delaysContentTouches = false
self.isPagingEnabled = false
self.showsHorizontalScrollIndicator = false
self.showsVerticalScrollIndicator = false
}
}
//MARK: - cache
extension SPPageCollectionView {
func setCachedImage(link: String, indexPath: IndexPath, on imageView: SPDownloadingImageView, cell: SPCollectionViewCell) {
if let image = self.fromCahce(link: link) {
imageView.setImage(image: image, animatable: false)
} else {
SPDownloader.image(link: link) { (response) in
if let image = response {
if cell.currentIndexPath == indexPath {
imageView.setImage(image: image, animatable: true)
self.toCache(link: link, image: image)
}
}
}
}
}
func toCache(link: String, image: UIImage?) {
if image == nil {
return
}
if self.fromCahce(link: link) == nil {
self.cacheImages.append((link: link, image: image!))
}
}
func fromCahce(link: String) -> UIImage? {
let cachedData = self.cacheImages.first(where: {
$0.link == link
})
return cachedData?.image
}
}
@@ -21,7 +21,7 @@
import UIKit
class SPNativeTableController: SPTableController {
public class SPNativeTableController: SPTableController {
let labelTableViewCellIdentifier: String = "labelTableViewCellIdentifier"
let textFieldTableViewCellIdentifier: String = "textFieldTableViewCellIdentifier"
@@ -42,7 +42,7 @@ class SPNativeTableController: SPTableController {
private var autoSpaceHeight: CGFloat = 35
override func viewDidLoad() {
override public func viewDidLoad() {
super.viewDidLoad()
self.statusBar = .dark
@@ -81,23 +81,23 @@ class SPNativeTableController: SPTableController {
self.updateLayout(with: self.view.frame.size)
}
override func numberOfSections(in tableView: UITableView) -> Int {
override public func numberOfSections(in tableView: UITableView) -> Int {
return super.numberOfSections(in: tableView)
}
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
override public func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
return super.tableView(tableView, numberOfRowsInSection: section)
}
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
override public func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
fatalError("SPNativeTableViewController - need ivveride cellForRowAt")
}
override func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
override public func tableView(_ tableView: UITableView, titleForHeaderInSection section: Int) -> String? {
return nil
}
override func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
override public func tableView(_ tableView: UITableView, titleForFooterInSection section: Int) -> String? {
return nil
}
@@ -159,7 +159,7 @@ class SPNativeTableController: SPTableController {
//MARK: - manage selection
extension SPNativeTableController {
override func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
override public func tableView(_ tableView: UITableView, shouldHighlightRowAt indexPath: IndexPath) -> Bool {
if let _ = tableView.cellForRow(at: indexPath) as? SPFormFeaturedTitleTableViewCell {
return false
@@ -173,7 +173,7 @@ extension SPNativeTableController {
//MARK: - manage spaces
extension SPNativeTableController {
override func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
override public func tableView(_ tableView: UITableView, viewForHeaderInSection section: Int) -> UIView? {
if section == 0 {
return self.showTopInsets ? super.tableView(tableView, viewForHeaderInSection: section) : nil
} else {
@@ -181,7 +181,7 @@ extension SPNativeTableController {
}
}
override func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
override public func tableView(_ tableView: UITableView, viewForFooterInSection section: Int) -> UIView? {
if section == self.tableView.lastSection {
return self.showBottomInsets ? super.tableView(tableView, viewForFooterInSection: section) : nil
} else {
@@ -189,7 +189,7 @@ extension SPNativeTableController {
}
}
override func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
override public func tableView(_ tableView: UITableView, heightForHeaderInSection section: Int) -> CGFloat {
let firstSection = self.tableView.firstSectionWithRows
if section == firstSection {
if self.showTopInsets {
@@ -217,7 +217,7 @@ extension SPNativeTableController {
}
override func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
override public func tableView(_ tableView: UITableView, heightForFooterInSection section: Int) -> CGFloat {
if section == self.tableView.lastSectionWithRows {
if self.showBottomInsets {
if self.autoBottomSpace {
@@ -21,7 +21,7 @@
import UIKit
class SPProposeController: SPController {
public class SPProposeController: SPController {
private let data: Data
internal let areaView = AreaView()
@@ -54,7 +54,7 @@ class SPProposeController: SPController {
fatalError("init(coder:) has not been implemented")
}
override func viewDidLoad() {
override public func viewDidLoad() {
super.viewDidLoad()
self.areaView.isHidden = true
@@ -79,7 +79,7 @@ class SPProposeController: SPController {
self.updateLayout(with: self.view.frame.size)
}
override func viewDidAppear(_ animated: Bool) {
override public func viewDidAppear(_ animated: Bool) {
super.viewDidAppear(animated)
if !self.isPresent {
self.present()
@@ -88,7 +88,7 @@ class SPProposeController: SPController {
}
private func present() {
SPVibration.impact(system: .warning)
SPVibration.impact(.warning)
self.areaView.frame.origin.y = self.view.frame.size.height
self.areaView.isHidden = false
SPAnimationSpring.animate(self.animationDuration, animations: {
@@ -99,7 +99,7 @@ class SPProposeController: SPController {
options: .transitionCurlUp)
}
override func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
override public func dismiss(animated flag: Bool, completion: (() -> Void)? = nil) {
let hide = {
self.view.backgroundColor = UIColor.black.withAlphaComponent(0)
@@ -21,11 +21,11 @@
import UIKit
class SPTableController: SPStatusBarManagerTableController {
public class SPTableController: SPStatusBarManagerTableController {
var activityIndicatorView = UIActivityIndicatorView.init()
override func viewDidLoad() {
override public func viewDidLoad() {
super.viewDidLoad()
self.activityIndicatorView.stopAnimating()
@@ -35,7 +35,7 @@ class SPTableController: SPStatusBarManagerTableController {
self.updateLayout(with: self.view.frame.size)
}
override func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
override public func viewWillTransition(to size: CGSize, with coordinator: UIViewControllerTransitionCoordinator) {
super.viewWillTransition(to: size, with: coordinator)
coordinator.animate(alongsideTransition: { (contex) in
self.updateLayout(with: size)
@@ -43,7 +43,7 @@ class SPTableController: SPStatusBarManagerTableController {
}
@available(iOS 11.0, *)
override func viewLayoutMarginsDidChange() {
override public func viewLayoutMarginsDidChange() {
super.viewLayoutMarginsDidChange()
self.updateLayout(with: self.view.frame.size)
}
@@ -21,11 +21,11 @@
import UIKit
class SPSectionLabelsView: SPView {
public class SPSectionLabelsView: SPView {
let titleLabel = UILabel()
let subtitleLabel = UILabel()
let button = UIButton.init(type: UIButton.ButtonType.system)
let titleLabel = SPLabel()
let subtitleLabel = SPLabel()
let button = SPButton()
override func commonInit() {
super.commonInit()
@@ -53,21 +53,24 @@ class SPSectionLabelsView: SPView {
self.layoutSubviews()
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.titleLabel.sizeToFit()
self.titleLabel.setWidth(self.frame.width)
self.titleLabel.frame.origin = CGPoint.zero
//self.titleLabel.backgroundColor = UIColor.lightGray
self.subtitleLabel.sizeToFit()
self.subtitleLabel.setWidth(self.frame.width)
self.subtitleLabel.frame.origin.x = 0
self.subtitleLabel.frame.origin.y = self.titleLabel.frame.bottomYPosition + 3
//self.subtitleLabel.backgroundColor = UIColor.darkGray
self.button.sizeToFit()
self.button.frame.bottomXPosition = self.frame.width
self.button.frame.bottomYPosition = self.titleLabel.frame.bottomYPosition
self.button.center.y = self.titleLabel.center.y
//self.button.backgroundColor = UIColor.darkGray
self.setHeight(self.subtitleLabel.frame.bottomYPosition)
}
@@ -21,7 +21,7 @@
import UIKit
class SPDownloadingImageView: SPImageView {
public class SPDownloadingImageView: SPImageView {
let activityIndiactorView = UIActivityIndicatorView.init()
let gradeView = UIView.init()
@@ -68,7 +68,7 @@ class SPDownloadingImageView: SPImageView {
self.gradeView.alpha = 1
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.gradeView.setEqualsBoundsFromSuperview()
self.activityIndiactorView.center = CGPoint.init(x: self.bounds.midX, y: self.bounds.midY)
@@ -21,7 +21,7 @@
import UIKit
class SPFooterActionsView: SPView {
public class SPFooterActionsView: SPView {
var sectionLabels = SPSectionLabelsView()
private var buttons: [SPFooterActionButton] = []
@@ -47,13 +47,20 @@ class SPFooterActionsView: SPView {
self.addSubview(separator)
}
func button(for id: Int) -> SPFooterActionButton? {
if (self.buttons.count - 1) < id {
return nil
}
return self.buttons[id]
}
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.setWidth(width)
self.layoutSubviews()
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.sectionLabels.layout(origin: CGPoint.zero, width: self.frame.width)
@@ -82,10 +89,30 @@ class SPFooterActionsView: SPView {
class SPFooterActionButton: SPButton {
var rightIconView: UIView? {
willSet {
self.rightIconView?.removeFromSuperview()
}
didSet {
if let view = self.rightIconView {
self.addSubview(view)
self.layoutSubviews()
}
}
}
override func commonInit() {
super.commonInit()
self.setTitleColor(SPNativeColors.blue)
self.titleLabel?.font = UIFont.system(type: .Regular, size: 21)
self.contentHorizontalAlignment = .left
}
override func layoutSubviews() {
super.layoutSubviews()
let sideSize: CGFloat = self.frame.height * 0.36
self.rightIconView?.frame = CGRect.init(x: 0, y: 0, width: sideSize, height: sideSize)
self.rightIconView?.center.y = self.frame.height / 2
self.rightIconView?.frame.bottomXPosition = self.frame.width - sideSize / 3
}
}
@@ -21,7 +21,7 @@
import UIKit
class SPGradeBlurView: UIView {
public class SPGradeBlurView: UIView {
internal var gradeView: UIView = UIView()
internal var blurView: UIView = UIView()
@@ -67,7 +67,7 @@ class SPGradeBlurView: UIView {
self.setBlurRadius(blurRaius)
}
override func layoutSubviews() {
override public func layoutSubviews() {
super.layoutSubviews()
self.gradeView.frame = self.bounds
self.blurView.frame = self.bounds
@@ -25,10 +25,10 @@ public class SPGradientView: SPView {
var gradientLayer: CAGradientLayer = CAGradientLayer()
var startColor: UIColor = UIColor.white { didSet { self.updateGradient() }}
var endColor: UIColor = UIColor.black { didSet { self.updateGradient() }}
var startColorPosition: Position = Position.TopLeft { didSet { self.updateGradient() }}
var endColorPosition: Position = Position.BottomRight { didSet { self.updateGradient() }}
var startColor = UIColor.white { didSet { self.updateGradient() }}
var endColor = UIColor.black { didSet { self.updateGradient() }}
var startColorPosition = Position.topLeft { didSet { self.updateGradient() }}
var endColorPosition = Position.bottomRight { didSet { self.updateGradient() }}
override func commonInit() {
super.commonInit()
@@ -48,32 +48,33 @@ public class SPGradientView: SPView {
}
public enum Position {
case TopLeft
case TopCenter
case TopRight
case BottomLeft
case BottomCenter
case BottomRight
case MediumLeft
case MediumRight
case topLeft
case topCenter
case topRight
case bottomLeft
case bottomCenter
case bottomRight
case mediumLeft
case mediumRight
var point: CGPoint {
switch self {
case .TopLeft:
case .topLeft:
return CGPoint.init(x: 0, y: 0)
case .TopCenter:
case .topCenter:
return CGPoint.init(x: 0.5, y: 0)
case .TopRight:
case .topRight:
return CGPoint.init(x: 1, y: 0)
case .BottomLeft:
case .bottomLeft:
return CGPoint.init(x: 0, y: 1)
case .BottomCenter:
case .bottomCenter:
return CGPoint.init(x: 0.5, y: 1)
case .BottomRight:
case .bottomRight:
return CGPoint.init(x: 1, y: 1)
case .MediumLeft:
case .mediumLeft:
return CGPoint.init(x: 0, y: 0.5)
case .MediumRight:
case .mediumRight:
return CGPoint.init(x: 1, y: 0.5)
}
}
@@ -21,7 +21,7 @@
import UIKit
class SPImageView: UIImageView {
public class SPImageView: UIImageView {
var round: Bool = false {
didSet {
@@ -21,7 +21,7 @@
import UIKit
class SPScrollView: UIScrollView {
public class SPScrollView: UIScrollView {
init() {
super.init(frame: .zero)
@@ -40,7 +40,7 @@ class SPScrollView: UIScrollView {
self.delaysContentTouches = false
}
override func touchesShouldCancel(in view: UIView) -> Bool {
override public func touchesShouldCancel(in view: UIView) -> Bool {
if view is UIControl
&& !(view is UITextInput)
&& !(view is UISlider)
@@ -29,14 +29,14 @@ class SPSeparatorView: SPView {
override func commonInit() {
super.commonInit()
self.backgroundColor = UIColor.init(hex: "515B66").withAlphaComponent(0.4)
self.backgroundColor = UIColor.init(hex: "515B66").withAlphaComponent(0.25)
self.round = true
self.setHeight(self.height)
}
func layout(origin: CGPoint, width: CGFloat) {
self.frame.origin = origin
self.set(width: width, height: self.height)
self.frame.origin = CGPoint.init(x: floor(origin.x), y: floor(origin.y))
self.set(width: floor(width), height: self.height)
}
override func layoutSubviews() {
@@ -21,7 +21,7 @@
import UIKit
class SPTextField: UITextField {
public class SPTextField: UITextField {
public var textInsets = UIEdgeInsets(top: 0, left: 0, bottom: 0, right: 0) {
didSet { setNeedsDisplay() }
@@ -21,26 +21,23 @@
import UIKit
class SPEmptyProposeLabel: UILabel {
class SPTextView: UITextView {
var cursorColor: UIColor = UIColor.blue {
didSet {
self.tintColor = self.cursorColor
}
}
init() {
super.init(frame: CGRect.zero)
super.init(frame: .zero, textContainer: nil)
self.commonInit()
}
init(title: String) {
super.init(frame: CGRect.zero)
self.text = title
self.commonInit()
}
private func commonInit() {
self.setCenteringAlignment()
self.font = UIFont.system(type: .Regular, size: 14)
self.textColor = SPNativeColors.gray
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
super.init(coder: aDecoder)
self.commonInit()
}
internal func commonInit() {}
}

Some files were not shown because too many files have changed in this diff Show More