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

Casualties of The Great Swiftening

Casualties of The Great Swiftening

We’re told that Swift is a more evolved language, but what of the many powerful Objective-C features that were lost along the way? We’ll look at some awesome concepts that are conspicuously absent from Swift and how to build them back into the language.

Originally presented at NSNorth 2014: http://nsnorth.ca

Source: https://github.com/jpsim/talks

JP Simard

April 11, 2015
Tweet

More Decks by JP Simard

Other Decks in Programming

Transcript

  1. QueryKit struct MyStruct { let intProp: Int struct Attributes {

    static let intProp = Attribute<Int>("intProp") } } // Usage let intProp = MyStruct.Attributes.intProp intProp > 0 // NSPredicate("intProp > 0"), typesafe
  2. Argo extension User: JSONDecodable { static func create(name: String)(email: String?)(role:

    Role) (friends: [User]) -> User { return User(name: name, email: email, role: role, friends: friends) } static func decode(j: JSONValue) -> User? { return User.create <^> j <| "name" <*> j <|? "email" // Use ? for parsing optional values <*> j <| "role" // Custom types conforming to JSONDecodable work <*> j <|| "friends" // parse arrays of objects } }
  3. as?

  4. protocol XPCConvertible {} extension Int64: XPCConvertible {} extension String: XPCConvertible

    {} func toXPC(object: XPCConvertible) -> xpc_object_t? { switch(object) { case let object as Int64: return xpc_int64_create(object) case let object as String: return xpc_string_create(object) default: fatalError("Unsupported type for object: \(object)") return nil } }
  5. /// The type returned by `reflect(x)`; supplies an API for

    runtime reflection on `x` protocol MirrorType { /// The instance being reflected var value: Any { get } /// Identical to `value.dynamicType` var valueType: Any.Type { get } /// A unique identifier for `value` if it is a class instance; `nil` otherwise. var objectIdentifier: ObjectIdentifier? { get } /// The count of `value`\ 's logical children var count: Int { get } subscript (i: Int) -> (String, MirrorType) { get } /// A string description of `value`. var summary: String { get } /// A rich representation of `value` for an IDE, or `nil` if none is supplied. var quickLookObject: QuickLookObject? { get } /// How `value` should be presented in an IDE. var disposition: MirrorDisposition { get } }
  6. struct MyStruct { let stringProp: String let intProp: Int }

    let reflection = reflect(MyStruct(stringProp: "a", intProp: 1)) for i in 0..<reflection.count { let propertyName = reflection[i].0 let value = reflection[i].1.value println("\(propertyName) = \(value)") if let value = value as? Int { println("int") } else if let value = value as? String { println("string") } } // stringProp = a // string // intProp = 1 // int
  7. import Foundation class objcSub: NSObject { let string: String? let

    int: Int? } var propCount: UInt32 = 0 let properties = clazz_copyPropertyList(objcSub.self, &propCount) for i in 0..<Int(propCount) { let prop = properties[i] String.fromCString(property_getName(prop))! // => "string" String.fromCString(property_getAttributes(prop))! // => "T@,N,R,Vstring" }
  8. nm -a libswiftCore.dylib | grep "stdlib" > ... > __TFSs28_stdlib_getDemangledTypeNameU__FQ_SS

    > ... > _swift_stdlib_conformsToProtocol > _swift_stdlib_demangleName > _swift_stdlib_dynamicCastToExistential1 > _swift_stdlib_dynamicCastToExistential1Unconditional > _swift_stdlib_getTypeName > ...
  9. struct MyStruct { let stringProp: String let intProp: Int }

    let reflection = reflect(MyStruct(stringProp: "a", intProp: 1)) for i in 0..<reflection.count { let propertyName = reflection[i].0 let value = reflection[i].1.value println("\(propertyName) = \(value)") println(_stdlib_getDemangledTypeName(value)) } // stringProp = a // Swift.String // intProp = 1 // Swift.Int
  10. struct _swift_data { unsigned long flags; const char *className; int

    fieldcount, flags2; const char *ivarNames; struct _swift_field **(*get_field_data)(); }; struct _swift_class { union { Class meta; unsigned long flags; }; Class supr; void *buckets, *vtable, *pdata; int f1, f2; // added for Beta5 int size, tos, mdsize, eight; struct _swift_data *swiftData; IMP dispatch[1]; };
  11. class GenericClass<T> {} class SimpleClass: NSObject {} class ParentClass {

    let boolProp: Bool? // Optionals let intProp: Int // Without default value var floatProp = 0 as Float // With default value var doubleProp = 0.0 var stringProp = "" var simpleProp = SimpleClass() var genericProp = GenericClass<String>() }
  12. { "boolProp": "b", "intProp": "i", "floatProp": "f", "doubleProp": "d", "stringProp":

    "S", "simpleProp": "ModuleName.SimpleClass", "genericProp": "[Mangled GenericClass]" }
  13. var _greet: String -> String = { "Hello, \($0)" }

    struct Conf { let name: String func greet() -> String { return _greet(name) } } let nsnorth = Conf(name: "NSNorth") nsnorth.greet() // => Hello NSNorth _greet = { _ in "nope" } // Avoiding Georgia's advice nsnorth.greet() // => nope
  14. struct NSNorth { var speakers: [String] { didSet { println("NSNorth

    changed their speakers") } } init(speakers: [String]) { self.speakers = speakers } } var nsnorth = NSNorth(speakers: existingSpeakers) nsnorth.speakers += ["Rob Rix"] // => prints "NSNorth changed their speakers"
  15. Lenses%in%Swi) struct Conference { let name: String let year: Int

    } struct Lens<A, B> { let from: A -> B let to: (B, A) -> A } let year = Lens(from: { $0.year }, to: { Conference(name: $1.name, year: $0) }) let nsnorth2 = Conference(name: "NSNorth", year: 2014) let nsnorth3 = year.to(2015, nsnorth2) // => Conference(name: "NSNorth", year: 2015)