Upgrade to Pro — share decks privately, control downloads, hide ads and more …

Hidden Gems in Swift

Hidden Gems in Swift

My talk from the April 2016 meeting of Brooklyn Swift!

Jasdev Singh

April 12, 2016
Tweet

More Decks by Jasdev Singh

Other Decks in Technology

Transcript

  1. > Literal convertible protocols > Experimental Operators > Apply mutating

    functions to immutable values > Attributes > Higher-level types for enum raw values > Metatypes > Custom pattern matching
  2. extension UIEdgeInsets: ArrayLiteralConvertible { public init(arrayLiteral elements: CGFloat...) { guard

    elements.count == 4 else { fatalError("4 CGFloats required!") } top = elements[0] left = elements[1] bottom = elements[2] right = elements[3] } } let insets: UIEdgeInsets = [10, 20, 10, 20] Swift Evolution: Tuple Convertible
  3. "Raw values can be strings, characters, or any of the

    integer or floating-point number types. Each raw value must be unique within its enumeration declaration."
  4. extension CGSize: StringLiteralConvertible { // Inspired by @terhechte public init(stringLiteral

    value: String) { let size = CGSizeFromString(value) self.init(width: size.width, height: size.height) } public init(extendedGraphemeClusterLiteral value: String) { let size = CGSizeFromString(value) self.init(width: size.width, height: size.height) } public init(unicodeScalarLiteral value: String) { let size = CGSizeFromString(value) self.init(width: size.width, height: size.height) } }
  5. enum DevicesClass: CGSize { case iPhone4 = "{320, 480}" case

    iPhone5 = "{320, 568}" case iPhone6 = "{375, 667}" case iPhone6Plus = "{414, 736}" } let jasdevPhone = DevicesClass.iPhone6.rawValue // `CGSize`
  6. // Credit to @jckarter func apply<T, U>(transform: inout T ->

    U -> Void) -> T -> U -> T { return { a in { b in var c = a transform(&c)(b) return c } } } let first = [1, 2, 3] let second = [4, 5, 6] let third = apply(Array.appendContentsOf)(first)(second)
  7. infix operator ∘ { associativity left precedence 100 } public

    func ∘<T, U, V>(g: U -> V, f: T -> U) -> (T -> V) { return { g(f($0)) } } infix operator ∖ { associativity left precedence 140 } infix operator ∖= { associativity right precedence 90 assignment } infix operator ∪ { associativity left precedence 140 } infix operator ∪= { associativity right precedence 90 assignment } infix operator ∩ { associativity left precedence 150 } infix operator ∩= { associativity right precedence 90 assignment } infix operator ⨁ { associativity left precedence 140 } infix operator ⨁= { associativity right precedence 90 assignment } infix operator ∈ { associativity left precedence 130 } infix operator ∉ { associativity left precedence 130 } infix operator ⊂ { associativity left precedence 130 } infix operator ⊄ { associativity left precedence 130 } infix operator ⊆ { associativity left precedence 130 } infix operator ⊈ { associativity left precedence 130 } infix operator ⊃ { associativity left precedence 130 } infix operator ⊅ { associativity left precedence 130 } infix operator ⊇ { associativity left precedence 130 } infix operator ⊉ { associativity left precedence 130 }
  8. @NONOBJC "Apply this attribute to a method, property, subscript, or

    initializer declaration to suppress an implicit objc attribute."
  9. extension NSUserDefaults { subscript(key: String) -> AnyObject? { get {

    return objectForKey(key) } set { setObject(newValue, forKey: key) } } subscript(key: String) -> Bool { // X - Subscript getter with Objective-C selector `objectForKeyedSubscript:` conflicts with previous declaration get { return boolForKey(key) } // X - Subscript setter with Objective-C selector `setObject:forKeyedSubscript:` conflicts with previous declaration set { setBool(newValue, forKey: key) } } // etc. }
  10. extension NSUserDefaults { @nonobjc subscript(key: String) -> AnyObject? { get

    { return objectForKey(key) } set { setObject(newValue, forKey: key) } } @nonobjc subscript(key: String) -> Bool { get { return boolForKey(key) } set { setBool(newValue, forKey: key) } } // etc. }
  11. @available "Apply this attribute to any declaration to indicate the

    declaration’s lifecycle relative to certain platforms and operating system versions."
  12. class SampleViewController: UIViewController { init() { super.init(nibName: nil, bundle: nil)

    } @available(*, unavailable) required init?(coder aDecoder: NSCoder) { fatalError("init(coder:) has not been implemented") } }
  13. @noreturn public func fatalError(@autoclosure message: () -> String = default,

    file: StaticString = #file, line: UInt = #line) fatalError("ayy lmao")
  14. // Credit to @pearapps extension Optional { func iff(@noescape f:

    Wrapped -> Void) { switch self { case let .Some(value): f(value) default: return } } } let foo: String? = nil func bar(a: String) { print(a) } if let foo = foo { bar(foo) } foo.iff(bar)
  15. "A metatype type refers to the type of any type,

    including class types, structure types, enumeration types, and protocol types."
  16. protocol Reusable: class { static var reuseIdentifier: String { get

    } } extension UITableView { func registerReusable<T: Reusable>(cellClass: T.Type) { registerClass(cellClass, forCellReuseIdentifier: cellClass.reuseIdentifier) } func dequeueReusable<T: Reusable>(cellClass: T.Type) -> T { guard let cell = dequeueReusableCellWithIdentifier(cellClass.reuseIdentifier) as? T else { fatalError("Misconfigured cell type, \(cellClass)!") } return cell } // ... }
  17. class CustomCell: UITableViewCell, Reusable { static let reuseIdentifier = "customCell"

    } class SomeTableViewController: UITableViewController { override func viewDidLoad() { super.viewDidLoad() tableView.registerReusable(CustomCell.self) } override func tableView(tableView: UITableView, cellForRowAtIndexPath indexPath: NSIndexPath) -> UITableViewCell { return tableView.dequeueReusable(CustomCell.self) } // ... }
  18. func ~=<T>(pattern: T -> Bool, value: T) -> Bool {

    return pattern(value) } func isEven<T: IntegerType>(a: T) -> Bool { return a % 2 == 0 } let x = 3 switch x { case isEven: print("even") default: print("odd") } @olebegemann's post on pattern matching
  19. SWIFT PRANK 1 func ~=<T, U>(_: T, _: U) ->

    Bool { return true } 1 Don't do this