Learning Swift

Notes written while Swift was being released to the world.

Tuesday 3 June 2014, writing my first app:

  • At the moment of this writing there is no support for “class” (or “static”) variables (although it seems to work with structs) which makes singletons almost impossible to write
  • No optional methods for protocols (only for Objective-C protocols)
  • Important point: the standard library. The types defined there are not the same as those from Foundation; the Foundation types can be used very easily, though.
  • No need to import files; all symbols are automatically available from every other file in the application.
  • “nil” can be used with value types, like Int and others (when optional, that is)
  • Type names start with uppercase, always
  • In the current version (first Beta after the WWDC) the first parameter of a function call must not have a parameter named specified; all the others must have a parameter name. Apparently it’s a bug.
  • Use the “as” keyword to force a return value to have a certain type. This information is used by the compiler. The variable type is not taken into account in some cases (useful in case of assignment of an instance of a subclass to a variable typed as its superclass)
  • Array is the same as String[] (syntactic sugar)
  • Functions are closures Xcode > Build Settings > Enable Strict Checking of objc_msgSend Calls = Yes https://twitter.com/gparker/status/473571205400645632

Wednesday 4 June 2014, watching the 1st WWDC video (session 402) about the language:

  • The standard library is included by default
  • Semicolons are optional
  • Safe, modern, powerful
  • var for variables, let for constants
  • String, Double, Int, Bool
  • Immutability / const by default -> preferred -> this allows the language to be optimized in multicore environments
  • Type inference makes (in most cases) the type definition useless
  • Unicode names for variables, including emoji
  • String is a Unicode compliant implementation
    • Looks like a C-String
    • Can be used everywhere an NSString is required
    • All the NSString API is available in native Swift strings
    • for character in “mouse” -> including full Unicode compatibility
    • “+” can be used to concatenate strings
    • “printf” -> let result = “(a) times (b) is (a * b)”
    • cannot “+” another string to a constant (var strings are mutable)
  • Array and Dictionary
    • Can be used just like NSArray or NSDictionary
    • Can be created with literals, just like in Objective-C
    • Keys and values can be anything, value or object
    • Collections are typed
    • var names: String[] = [“boom”, “bam”] -> the typed is inferred from the assignment
    • Typed collection are safe, enforced by the compiler and the IDE
    • Loops -> while, for, for in.
    • For loops can have ranges “1…5” with three dots between the bounds (bounds are included)
    • But “0..5” (with two dots) does not include the 5
    • Can “for in” with dictionaries, which uses “for (key, value) in dict { … } “
  • Modifying arrays
    • The += operator can be used to add one or many (using another array) objects to an array
    • “array[0…5] = …” can be used to replace lots of objects at once
  • Optionals
    • Indicated with question marks. It means that a type might contain something OR nil.
    • Nil can be used with values
    • The exclamation mark is an “unwrap” operator, to force the value out
    • The exclamation mark triggers an assertion if the value stored is nil
    • Better and safe: “if let obj = optional {…} “
  • If statements don’t require parenthesis
    • But they do require curly braces
  • Switch statements do not fallback -> break statement not required.
    • Don’t need to “case” numbers only, but also strings and objects
    • Case statements can match multiple values in a single case
    • Switch statements MUST be exhaustive: they MUST have a case for every possible value; you can use a “default” keyword for “the other values”
    • Cases can match against a range
  • println
    • defined in the standard library
  • Functions
    • Use the func keyword
    • Default values: func sayHello(name: String = “World”) {…}
    • Return types specified using “->” and the type
  • Tuples
    • Can return multiple values using a tuple: (3.70, 3.25, 6.7) or (404, “Not Found”)
    • Not a replacement for complex types or collections
    • let (statusCode, message) = (200, “Success”)
      • The tuple is (Int, String)
    • Used when enumerating dictionaries
    • Values in tuples can be named: (code: Int, message: String) -> let status = tuple -> tuple.code, tuple.message
  • Closures
    • Blocks like in Objective-C
    • Type of a void/void closure is “() -> ()”
    • Functions are named closures
    • Can be passed as parameters
    • If the closure is the last parameter, it can be passed outside of the parenthesis as a “trailing closure”
  • Classes
    • Don’t need to import .h files (no header files)
    • Swift does not have a universal base class; can use any Objective-C class if required
    • variable declarations in classes become properties
    • Ivars and properties are the same
    • Stored properties and computed properties, using a “get” keyword with a block inside returning a value, similar to C# (the “get” is not really required if the variable is readonly)
    • Instantiation like Python, no “new” keyword
    • Dot syntax for properties and methods
    • All members are public
    • “init()” is the initialiser of the class
      • super.init() required
      • No return
    • “override” keyword to override a property in a subclass -> type safety
    • Property observers using a “willSet” or “didSet” observer on the overridden properties; that code is in-place KVO code executed automatically
    • In methods “self.” is optional when referring to properties, can be used to avoid confusion
  • Structures
    • “struct” keyword
    • Can have custom initialisers
    • Can have computed properties
    • Can have methods
  • Struct vs Class; differences?
    • Struct cannot inherit
    • Structs are passed as value (copy,) class instances as reference
    • Constants and variables:
      • Constants to a class instance can be used to change the properties of the referred object, but I cannot change the reference itself
      • Constants to structs are immutable, and this includes the properties of the struct. The whole struct values are immutable too
      • Hence, to mutate a structure on a method YOU HAVE TO USE the “mutating” keyword in front of the method declaration
  • Enumerations
    • .toRaw() method returns the raw integer value of an enumeration
    • Enumerations can be based on other raw values, like strings
    • Sometimes, no underlying raw value at all
    • can use the “.Value” to change enum variables
  • Enumerations with associated values
    • enum TrainStatus { case OnTime, case Delayed(Int) }
    • status = .Delayed(10)
    • enums can have initializers and computed properties
  • Type nesting
    • A class can define its own internal enums
  • Extensions
    • Like a category in Objective-C
    • Any named type, including value types, in any framework
  • Generics
    • Works for classes and structs
    • Similar syntax as in Java or C#

“@Catfish_Man @siracusa Swift doesn’t dispatch through objc_msgSend() unless you inherit from NSObject or mark @objc. It’s pretty crazy.” https://twitter.com/brentdax/status/473929502955823106

Every iOS/OS X dev conference talk for the next ten years is going to have Swift code with the poop emoji as a variable name. https://twitter.com/mattgemmell/status/474104244384305152

Seems odd that Swift is still using @ prefixes for certain keywords (such as at the lazy modifier) - does anyone know why that is? https://twitter.com/nicklockwood/status/474178519468343297

Most perplexing feedback on Swift: folks who see it (and judge it) as the end of a trek - but don’t realize it is the start of a new world. https://twitter.com/clattner_llvm/status/474082459860992000

Looking forward to next month: I’ll be the first and only guy with 4 years of swift programming experience :-) https://twitter.com/clattner_llvm/status/473835365137416192

http://www.raywenderlich.com/73967/swift-cheat-sheet-and-quick-reference

Thursday 5 June 2014: Notes from session 406, “Integrating Swift with Objective-C”

  • Swift and Objective-C are both first-class citizens in Cocoa
  • Xcode creates a “bridging header” when adding a Swift class to an Objective-C project
  • It also generates a generated header that allows the inverse operation

The .swift Icon is the “Crazy Ones” text now. 😊 (via @blunckalex) http://t.co/JA63Fs5iyG https://twitter.com/_nb/status/474569926297276416

Of course Swift supports hashbang scripts, you can immediately execute a swift script with “xcrun swift -i”. https://twitter.com/clattner_llvm/status/474593140511211520

Observations while creating sb2code:

  • Port of nib2objc to Swift
  • Can generate Swift, ObjC (classic with setters, modern with @properties,) C# (Xamarin) and maybe more later.
  • New architecture that allows to read OSX storyboards and generate AppKit code
  • Unfortunately the compiler chokes over the large number of classes (there’s one handler class per managed object on the Storyboard)
  • Swift can return a “class” object from any class using the “.self” property, and this object is of type “.Type”
    • For example: “var type: String.Type = String.self”
  • Command-line tool at the moment does not have access to the command-line arguments (so far at least) so I’m using NSProcessInfo instead (as suggested by a question on devforums.apple.com)
  • I had to create the bridging header manually to import an NSString category manually into Swift (see above picture,) but it did work.
  • At the moment you cannot call sscanf (or other C standard libraries) directly from Swift, so you can use a bridging header for that wrapping on Objective-C. http://fuckingclosuresyntax.com http://goshdarnclosuresyntax.com

Friday 6 June 2014: Intermediate (403) and advanced (404) Swift sessions in WWDC

  • Argument names and parameter names can be different in the class or function definition
  • Argument names can be avoided using the underscore as an argument name in the definition
  • sort() is a function that returns an array. Array.sort() does not return a new array; it just orders the current one in place. This means that you cannot change Array.sort().filter().map()… etc because Array.sort() returns Void.
  • Variables must be initialised in init() prior to calling super.init() -> this is to ensure object initialisation before calling virtual methods, similar to what C++ does
  • Use @lazy in front of a property to create a lazy-loading property; its value will only be loaded when required the first time.
  • Special protocols the compiler knows about: LogicValue, Printable, Sequence, IntegerLiteralConvertible…
  • “Printable” protocol has a “description” read-only property
  • Operator overloading using the @infix keyword
  • Method overloading is possible, to receive different value types
  • “Any” is an “empty protocol” and it throws away type information. Generics conserve type information, providing performance and type safety
  • Trailing closure syntax (when closures are the last argument) brings memories of Ruby blocks
  • Generics can be applied to classes, functions, closures, structs…
  • The “Sequence” protocol is required to objects used in “for…in” enumerations
  • Protocols let you hook into the core language elements Swift model:
  • Swift is statically compiled, with a small runtime
  • Transparent interaction with C and ObjC
  • Can deploy to previous versions of iOS and OS X
  • Predictable compilation, no JIT or GC
  • Efficient: native code, no abstraction, bare-to-the-metal
  • During compilation, Swift analyses the code and optimises it
  • Structs have no runtime penalty
  • Int and Float are structs
  • Generic specialisation “can” happen, but it’s not mandatory as in C++; some code can run in generic mode at runtime
  • Dynamic method calls at compile-time: if Swift knows that there aren’t subclasses, or if you use the @final keyword

That’s one very strong statement: Swift is a protocol based language. https://twitter.com/fabricetdc/status/474824367126638592 (heard in session 404, minute 51)

In swift, “==” is compiled to [object1 isEqualTo:object2]. Something Cocoa developers have been begging for. “===” behaves as “==” in C. https://twitter.com/rosyna/status/474746076864344065

Swift web view tutorial video: https://www.youtube.com/watch?v=-wQ8sVa9TbU

Swift performance tip: compile your code in -Ofast mode to remove runtime safety checks. Your code will run much faster. https://twitter.com/SwiftDevs/status/474988521623916544

Safety and immutability are preferred, but Swift has UnsafePointer, malloc(), and mutability for the times you still need or want them https://twitter.com/clattner_llvm/status/475026273870180352