Swift in brief

Swift is a high-performance system programming language. It has a clean and modern syntax, offers seamless access to existing C and Objective-C code and frameworks, and is memory safe by default.


Although inspired by Objective-C and many other languages, Swift is not itself a C-derived language. As a complete and independent language, Swift packages core features like flow control, data structures, and functions, with high-level constructs like objects, protocols, closures, and generics. Swift embraces modules, eliminating the need for headers and the code duplication they entail.

The Basics

– Type-safe, type checks when compiling, type inference
– Fundamental types: Int, Double, Flow, Bool, String
– Collection types: Array, Set, Dictionary
– Provide signed & unsigned integers in 8,16,32, 64 forms
– Double: 64-bit, Float is 32-bit floating point number
– Tuple: group of multiple values of any type
– Optional: Either there is a value or nothing at all, optional binding using if let, implicitly unwraped optional using !

Basic Operators

– Operators: unary, binary, ternary
– Arithmatic operators do not allow overflow by default
– Range operators: closed a…b, half-open a..<b, one-sided items[a…]/items[…a]/items[..<a]
– Operators && and || are left-associative, use short-circuit evaluation
– Nil-coalescing operator (a ?? b), use short-circuit evaluation

Strings & Characters

– String mutability is managed by choosing between constants and variables
– Multiline string literal is a sequence of characters surrounded by three double quotes “””
– Unicode is international standard for encoding, representing and processing text
– Swift’s native String type is built from Unicode scalar values
– UTF-8, UTF-16, Unicode scalar 21-bit value represented in UInt32
– Extended grapheme cluster is an sequence of one or more Unicode scalars that produce a single character
– String interpolation & concatenation

Collection Types

– Arrays are ordered collections of values
– Sets are unordered collections of unique values (Type must be hashable)
– Dictionaries are unordered collections of key-value associations (Key must be hasable)
– Implemented as generic collections, clear about types of values and keys,
– Hastable, Equatable, Reflexivity, Symmetric, Transitivity, Intersection, Union, Subtracting, SymmetricDifference

Control Flow

– Multiple times: while, repeat-while, for-in
– Conditional statements: if , switch
– Control transfer statements: break, continue, fallthrough, return, throw
– Early Exit : guard
– Checking API Availability: #available

Functions

– functions are self-contained chunks of code that perform a specific task
– Variadic parameters : (…) pass a varying number of input values, a function may have at most one
– Function parameters are constants by default, in-out parameters can not have default values, variadic parameters cannot marked as inout
– function types
– nested functions

Closures

– Closures : global functions that have a name and do not capture any values, nested functions that have a name and can capture values from their enclosing function, unnamed closures written in lightweight syntax that can capture values from their surrounding context, are reference types
– Closure’s optimizations: Inferring parameter and return value types from context, implicit return from single-expression closures, shorthand argument names, trailing closure syntax
– @escaping: when the closure is passed as an argument to the function, but is called after the function returns
– Closures are reference types
– autoclosures: auto created to wrap an expression that’s being passed as an argument to a function

Enumerations

– an enumeration defines a common type for a group of related values
– first-class type: computed properties, instance methods, initializers, extension, protocol conformance
– associated values: different each time you create
raw values: string, character, integer, floating-point number. always the same for a particular case
implicitly assigned raw values: integer will auto increate, string will use text of case’s name
initializing from a raw value
– recursive enumeration : using indirect keyword

Classes & Structures

– Class & struct in common: properties, methods, subscript, initilazation, extensions, protocols
– Class better than struct when: inheritance, type casting, deinitilazation, ARC
– Using struct when: want to pass by value, don’t need inheritance, properties are value types
memberwise initializers for structure types
– Type property using static and class(allow subclass to overrdie)
– Structures and enumerations are value types. by default, properties of value type cannot be modified within its instance meethods. However you can opt-in to this behavior by using mutating keyword
– identical to (===), not identical to (!==) -> exactly the same class instance
equal to (==), not equal to (!=) -> equal in value
– In Swift String, Array and Dictionary are implemented as structures, this means they value types
– In Foundation NSString, NSArray and NSDictionary are reference types

Properties

– Stored properties: store constant and variable as part of an instance (class, struct)
– Computed properties: calculate a value (class, struct, enum)
– Type properties : associated with a Type
– Property observers (willSet, didSet): to monitor changes in property’s value, applied to self defined stored properties(except lazy) or inherited stored & calcuated properties. Self defined calcuated properties can use getter setter to observe
– Stored properties of constant structure instance cannot be modified because structure is value type (the same is not true for class, which is reference type)
– Lazy stored property: initial value is not calculated until the first use, useful for unknown outside factor/complex setup/computationaly expensive setup. There is no guarantee of once initialization if accessed by multiple threads
– Global and local variables (outside/inside function/method/closure). Global (always computed lazily), Local(never computed lazily)
– Stored type properties must always given a default value , lazily initialized by default
– Type properties use static keyword, class keyword is used for class to allow subclass to override

Methods

– Methods are functions that associated with a class, structure or enumeration (both instance & type)
– Modifying value types (structure & enum) from within instance methods using mutating
– Cannot call a mutating method on a constant of structure type
– Can assign to self in a mutating method
– Type method using static keyword. class keyword is used for class only to allow subclass to override

Subscripts

– classes, structures and enumerations can define subscripts
often used as shortcuts for accessing the member elements of a collection, list or sequence.
but you are free to implement subcripts in the most appropriate way for your particular class or structure
– support variadic,overloading, multiple dimensions & multiple input parameters
don’t support in-out or default values
– can be read-write or read-only using getter & setter

Inheritance

– base class, subclass, superclass,subclassing, overriding methods, properties, property getters and setters, property observers, accessing superclass methods, properties and subcripts
– preventing overrides using final keyword

Initialization

– Preparing instance of class, structure or enumeration
– Setting intial values for stored properties
– Swift provides an automatic argument label for every paramter if you don’t provide one
– Initializer parameters without argument labels (_)
– For class instances, constant property can be modified during initialization only by the class that introduces it, not by subclass
– Default initializer : available if providing default values for all properties, not having at lease one initializer itself
– Memeberwise initializer for structure types: availalbe if do not define own custom initializers, even if it has stored properties without default values
– Initializer delegation for value types
– Class desinated initializers: fully initializes all properties
– Class convenience initializers: supporting, call a desinated initializer
– A designated initializer must call a designated inititilizer from its immediate superclass
– A convenience initializer must call another initializer from the same class
– A convenience initializer must ultimately call a designated initializer
– Two-phase initialization: each stored property is assigned an initial value by the class introduced it -> give the opportunity to customize its stored properties further
– Initializer inheritance and overriding: Swift subclasses do not inherit their superclass initializers by default, you do not write the override modifier when providing a matching implementation of a superclass conveience initializer
– Automatic initializer inheritance: subclass ihherits all of its superclass designated initializers if it doesn’t define any designated initializers, sublcass inherits all superclass convenience initializers if it has implemented all superclass designated initializers both by inherites or override
– Failable initializers
– Required initializers

Deinitialization

– A deinitializer is call immediately before a class instance is deallocated
Only availalbe on class types, at most one per class, no parameters, no parentheses, called automatically
– Can access all properties of the instance

ARC

– Reference counting on classes & closures
– Strong reference cycles
– weak, unowned, unowned(safe), unowned(unsafe)
– Capture lists

Optional Chaining

– similar to messaging nil in ObjC, but in a way that work for any type
– alternative to force unwrapping
– Accessing properties, methods, subscripts

Error Handling

– Propagating errors using throwing functions
– do-catch, try, try?, try!, propagate again
– Specifying cleanup actions using defer

Type Casting

– Type checking operator (is)
– Type cast operator (as? or as!)
– Type casting for Any and AnyObject

Nested Types

– Type can be nested to as many levels as are required

Extensions

– Extensions add new functionality to an existing class, structure, enumeration or protocol
– Cannot override existing functionality
– Similar to Categories in OjbC but do not have names
– Capabilities: computed properties(instance & type), methods(instance & type), new convenience initializers, subscripts, new nested types, conform to protocol

Protocols

– A protocol defines a blueprint of methods, properties and other requirements that suit a particular task or functionality
– Can be adopted by classes, structures, enumerations
– Used for requirements of: property, method, mutating method, initializer
– Protocol are fully-fledged type for use in your code
– Delegation, protocol inheritance, protocol composition, protocol extension
– Adding protocol conformance with extension
– Class-only protocol inherit AnyObject
– Optional protocol requirements: both protocol and optional requirement must be marked with @objc, can be adopted only by classes that inherit form ObjC classes or other @objc classes
– Adding constraints to protocol extensions using where clause

Generics

– Generic functions: can work with any type, multiple type parameters <X,Y,Z> : can be used for parameters, return type, type annotation in body
– Generic types: custom classes, structures and enumerations that can work with any type
– Extending a generic type: original type is available within the body of extension
– Type Constraint: <T: SomeClass, U: SomeProtocol>
– Associated Type: gives a placeholder name to a type that is used as part of the protocol, the actual type is specified until protocol adopted, using type annotations to constraint an associated type (associatedtype Item: Equatable), can use with where clause (associatedtype Iterator:IteratorProtocol where Iterator.Element == Item)
Generic where clauses : to define requirements for associated types
– Extension with a genegic where clause (extension Stack where Element: Equatable, extension Container where Item: Equatable)
– Generic subcripts (subscript<Indices: Sequence>(indices: Indices) -> [Item] where Indices.Iterator.Element == Int)

Access Control

– based on: module & source file
open, public(module only subclass & override), internal, file-private, private
– access levels for single-target apps: default internal, file-private, private
– access levels for frameworks: mark an entity as open/public if you want it to become part of your framework’s API
– access levels for unit test targets: @testable for a module to access internal entity
a subclass cannot have higher access level than its superclass

Advanced Operators

– Bitwise operators: NOT(~), AND(&), OR(|), XOR(^), Left shift (<<), right shift (>>)
– Overflow operators: addition (&+), subtraction(&-), multiplication(&*)
– Precedence(priority), Associativity(left, right)
– Operator overloading (except default assignment operator = and ternary condition operator)
Prefix and postfix operators
– Compound assignment operators: +=, -=, *=,
– Equivelance operators : “equal to” ==, “not equal to” !=

Swift is better than Ojective C

– easier to read
– easier to maintain
– safe, modern & powerful
– unified with memory management
– requires less code
– faster
– fewer name collisions
– support dynamic libraries
– playgrounds encourages interactive coding
– a future you can influence