General syntax
/* /* comments can be nested */ */
- float constants can be expressed as
1.23e3
- any numbers can have underscores in them,
1_000_000
- indenting the closing
""" will ignore whitespace at the beginning of every line for multi line strings
Operators
- nil coalescing operator
(a ?? b), uses b when a is nil
&& || are left-associative, && does not have precedence
- Array has
init(repeating:count:) instead of arrayWithCapacity:
- Arithmetic operators do not overflow, causes error instead (can get c behavior with
&+ &- or &*)
- the standard operators can be defined for custom types. brand new operators can be declared globally with
operator
Flow control
- for complex for loops,
stride(from:through:by:)
do { try statement } catch { }
- repeat-while is swift speak for do-while
- switches do not fallthrough, unless explicitly requested. can still use break.
- multiple cases on a line with commas, can use ranges, can use where clause
- label loops/switches to break a specific one
- guard is like a reverse if statement for optionals.
guard let x = optVar else {}, where thing is an optional, t is available to rest of scope, not the else block.
Parameters
- use tuples to return multiple values
- function parameters can have default values, parameterWithDefault: Int = 12
- variadic parameters are referenced inside the function in as an array of the appropriate type
- parameters can be "inout", modifying the caller, called with &varName
- functions can be nested
Closures
- closure syntax:
{ arg1,arg2 in blah blah; return thing }
- single expression closure can omit return keyword
- argument list can be omitted in exchange for using $0, $1, $2, etc
Types
a==b always means equivalent, don’t need a.isEqualToString(b)
a===b means a and b are the same instance, not just equivalent objects
- structures are always passed by value, classes are passed by reference; otherwise they are very similar
- String, Array, Dictionary are swift structures, ie they are always copied when assigned. (swift won’t literally copy the memory until written to though)
- functions in structs cannot modify self (since its a value type), unless marked mutating
Class initialization
- can initialize properties on the line they are declared
- properties can be marked lazy, they will not be initialized until used
- computed properties have no storage, but do have accessors i.e.
var center: Point {get {...return} set {newValue...}}
- also used to define a subscript(). can omit get/set keywords if get is all that is desired.
- type properties are marked static, and are related to the type, not an instance. accessed from instance.var
- type methods are also marked static. or marked class, which lets subclasses override. accessed from Type.method
- to override properties or methods from a superclass, they must be marked "override"
- overrides can be prevented by marking a property, method, or class as final
- convenience init() is a method that will call another init() method in the same class. usually has simpler parameters
- init() must call a superclass non-convenience init eventually
- required init() means subclasses must override it
- deinit {...} to handle code right before deallocation. ARC handles all memory, so it’s just for other resources
Errors, Exceptions
- no difference between Error and Exception. there is no Exception, Errors are thrown.
- throw does not unwind the stack, and is comparable in performance to return.
try? will convert the error to an optional return
try! tells the compiler that a thrown error can’t happen and should be ignored (will cause a crash if it does)
defer {} blocks will execute when the current scope is exited for any reason (including errors) ie: closing opened files
Inheritance
- there is no global base class such as NSObject
- use
is and as for type casting, can use in a switch statement also.
- you can nest types inside other types
- extension is swift speak for category
- generics: use
<T> after class or function name, T is a placeholder for any type. ie Array<T>
- you can constrain the generic types, ie
Dictionary<Key :Hashable, Value>
Access levels
- The access levels are
- open(subclass/override when imported as a module)
- public(can’t subclass when imported)
- internal(to a module/framework/app/etc)
- fileprivate
- private(to a class/scope/etc)
- the default access level for everything is internal
- use
private(set) to change the access level for only a setter, leaving the getter public
Protocols
- protocols that inherit from
AnyObject can only be applied to classes, not structures
- you can require multiple protocols as a type, ie
[ProtA & ProtB] is an array of objects that conform to both ProtA and ProtB
- protocols can have optional methods, but can only be used on subclasses of NS-objc classes. This is not supposed to be used with swift, just an objc interoperability feature
- protocol methods can have default implementations, which is what you need when you want optional methods
ARC
- variables can be marked weak, but then must also be optional because it will become nil when the object is deallocated
- alternatively, marked unowned, which will not be set to nil, but should be used when you are certain it will always have a value