Swift+Sweeter.swift 3.2 KB

123456789101112131415161718192021222324252627282930313233343536373839404142434445464748495051525354555657585960616263646566676869707172737475767778798081828384858687888990919293949596979899100101
  1. //
  2. // Swift+Sweeter.swift
  3. //
  4. // Created by Yonat Sharon on 2019-02-21.
  5. //
  6. public extension CaseIterable where Self: Equatable {
  7. /// Sweeter: Index of current case in `allCases`.
  8. var index: Int {
  9. let all = Array(Self.allCases)
  10. return all.firstIndex(of: self)! // swiftlint:disable:this force_unwrapping
  11. }
  12. }
  13. // from https://gist.github.com/siejkowski/a2b187800f2e28b53c96
  14. public extension Sequence where Element: Optionable {
  15. /// Sweeter: Shorthand for `compactMap { $0 }`.
  16. var compact: [Element.Wrapped] {
  17. return compactMap { $0.value }
  18. }
  19. }
  20. public protocol Optionable {
  21. associatedtype Wrapped
  22. var value: Wrapped? { get }
  23. }
  24. // extension for Optional provides the implementations for Optional enum
  25. extension Optional: Optionable {
  26. public var value: Wrapped? { return self }
  27. }
  28. infix operator =?: AssignmentPrecedence
  29. /// Sweeter: Assign iff right side is not nil.
  30. public func =? <T>(lhs: inout T, rhs: T?) {
  31. if nil != rhs, let rhs = rhs {
  32. lhs = rhs
  33. }
  34. }
  35. public protocol DefaultConstructible {
  36. init()
  37. }
  38. extension Optional: DefaultConstructible {
  39. public init() {
  40. self = .none
  41. }
  42. }
  43. extension IntegerLiteralType: DefaultConstructible {}
  44. extension BooleanLiteralType: DefaultConstructible {}
  45. extension FloatLiteralType: DefaultConstructible {}
  46. extension StringLiteralType: DefaultConstructible {}
  47. extension Array: DefaultConstructible {}
  48. extension Dictionary: DefaultConstructible {}
  49. extension Set: DefaultConstructible {}
  50. // based on https://sveinhal.github.io/2016/03/16/retain-cycles-function-references/
  51. /// Sweeter: Pass a member function as an @escaping closure without retaining its object.
  52. ///
  53. /// Example: `var closure = weak(self, in: MyClass.someFunction)`
  54. public func weak<T: AnyObject>(_ instance: T, in classFunction: @escaping (T) -> () -> Void) -> () -> Void {
  55. return { [weak instance] in
  56. guard let instance = instance else { return }
  57. classFunction(instance)()
  58. }
  59. }
  60. /// Sweeter: Pass a member function as an @escaping closure without retaining its object.
  61. ///
  62. /// Example: `var closure = weak(self, in: MyClass.someFunction)`
  63. public func weak<T: AnyObject, U>(_ instance: T, in classFunction: @escaping (T) -> (U) -> Void) -> (U) -> Void {
  64. return { [weak instance] arguments in
  65. guard let instance = instance else { return }
  66. classFunction(instance)(arguments)
  67. }
  68. }
  69. /// Sweeter: Pass a member function as an @escaping closure without retaining its object.
  70. ///
  71. /// Example: `var closure = weak(self, in: MyClass.someFunction)`
  72. public func weak<T: AnyObject, V: DefaultConstructible>(_ instance: T, in classFunction: @escaping (T) -> () -> V) -> () -> V {
  73. return { [weak instance] in
  74. guard let instance = instance else { return V() }
  75. return classFunction(instance)()
  76. }
  77. }
  78. /// Sweeter: Pass a member function as an @escaping closure without retaining its object.
  79. ///
  80. /// Example: `var closure = weak(self, in: MyClass.someFunction)`
  81. public func weak<T: AnyObject, U, V: DefaultConstructible>(_ instance: T, in classFunction: @escaping (T) -> (U) -> V) -> (U) -> V {
  82. return { [weak instance] arguments in
  83. guard let instance = instance else { return V() }
  84. return classFunction(instance)(arguments)
  85. }
  86. }