Swift Cheat Sheet
Swift Cheat Sheet
Stolen from iwasrobbed.
I simplify it and add some more.
It’s a high level and a quick reference to Swift. The purpose of this cheat sheet is to teach myself and get answers within 10s.
Table of Contents
- Code Document
- Data Types
- Operators
- Operator Overloading
- Declaring Classes
- Declarations
- Lazy Property
- Property Observer
- Literals
- Functions
- Constants and Variables
- Naming Conventions
- Closures
- Generics
- Control Statements
- Extension
- Protocol
- Protocol Extension
- Error Handling
- Passing Information
- User Defaults
- Common Patterns
- Unicode Support
- File IO
Code Documentation
Two ways of commenting:
- //
- /* … */
Two ways of documenting with markdown (Reconigzed by xcode):
- ///
- /** … */
Markdown
a few keywords that xcode can recognized automatically, with the format like -
The most common: Prameters, Throws, Returns
|
|
Other keywords
|
|
Metadata
|
|
MARK
Using MARK
to organize your code:
|
|
FIXME
Using FIXME
to remember to fix your code:
|
|
FIXME
works a lot like MARK
because it makes organizing code easier, but it’s used exclusively when you need to remember to fix something.
TODO
Using TODO
to remember to add, delete, or generally refactor your code:
|
|
TODO
is very similar to FIXME
and MARK
, but it’s used exclusively when you need to remember to add, delete, or change your code later.
Auto-generating method documentation:
In a method’s preceding line, press ⌥ Option + ⌘ Command + /
to automatically generate a documentation stub for your method.
Data Types
Size
Permissible sizes of data types are determined by how many bytes of memory are allocated for that specific type and whether it’s a 32-bit or 64-bit environment. In a 32-bit environment, long
is given 4 bytes, which equates to a total range of 2^(4*8)
(with 8 bits in a byte) or 4294967295
. In a 64-bit environment, long
is given 8 bytes, which equates to 2^(8*8)
or 1.84467440737096e19
.
For a complete guide to 64-bit changes, please see the transition document.
C Primitives
Unless you have a good reason to use C primitives, you should just use the Swift types to ensure compability going foward.
In fact, Swift just aliases C types to a Swift equivalent:
|
|
From the docs:
C Type | Swift Type |
---|---|
bool | CBool |
char, signed char | CChar |
unsigned char | CUnsignedChar |
short | CShort |
unsigned short | CUnsignedShort |
int | CInt |
unsigned int | CUnsignedInt |
long | CLong |
unsigned long | CUnsignedLong |
long long | CLongLong |
unsigned long long | CUnsignedLongLong |
wchar_t | CWideChar |
char16_t | CChar16 |
char32_t | CChar32 |
float | CFloat |
double | CDouble |
Integers
Integers can be signed or unsigned. When signed, they can be either positive or negative and when unsigned, they can only be positive.
Apple states: Unless you need to work with a specific size of integer, always use Int
for integer values in your code. This aids code consistency and interoperability. Even on 32-bit platforms, Int
[…] is large enough for many integer ranges.
Fixed width integer types with their accompanying byte sizes as the variable names:
|
|
Floating Point
Floats cannot be signed or unsigned.
|
|
Boolean
|
|
In Objective-C comparative statements, 0
and nil
were considered false
and any non-zero/non-nil values were considered true
. However, this is not the case in Swift. Instead, you’ll need to directly check their value such as if x == 0
or if object != nil
Primitives
nil : Used to specify a null object pointer. When classes are first initialized, all properties of the class point to nil
.
Enum & Bitmask Types
Enumeration types can be defined as follows:
|
|
As of Swift 3, all enum options should be named in lowerCamelCased.
Working with Bitmasks
Newer Swift versions have a nice substitute for the old NS_OPTIONS
macro for creating bitmasks to compare to.
An example for posterity:
|
|
Type Casting
Sometimes it is necessary to cast an object into a specific class or data type. Examples of this would be casting from a Float
to an Int
or from a UITableViewCell
to a subclass such as RPTableViewCell
.
Checking Types
Swift uses is
and as
both for checking object types as well as conformance to a given protocol.
Operator: is
Checking object type using is
:
|
|
The is
operator returns true
if an instance is of that object type, or conforms to the specified protocol, and returns false
if it does not.
Operators: as? and as!
If you want to be able to easily access the data during one of these checks, you can use as?
to optionally (or as!
to force) unwrap the object when necessary:
|
|
The as?
version of the downcast operator returns an optional value of the object or protocol’s type, and this value is nil
if the downcast fails or this instance does not conform to the specified protocol.
The as!
version of the downcast operator forces the downcast to the specified object or protocol type and triggers a runtime error if the downcast does not succeed.
Casting from Generic Types
If you’re working with AnyObject
objects given from the Cocoa API, you can use:
|
|
If given an array with Any
objects, you can use a switch
statement with the type defined for each case
:
|
|
Basic Casting
Swift also offers some simple methods of casting between it’s given data types.
|
|
Operators
Swift supports most standard C operators and improves several capabilities to eliminate common coding errors. The assignment operator =
does not return a value, to prevent it from being mistakenly used when the equal to operator ==
is intended.
Arithmetic operators (+
, -
, *
, /
, %
) detect and disallow value overflow, to avoid unexpected results when working with numbers that become larger or smaller than the allowed value range of the type that stores them.
Arithmetic Operators
Operator | Purpose |
---|---|
+ | Addition |
- | Subtraction |
* | Multiplication |
/ | Division |
% | Remainder |
Comparative Operators
Operator | Purpose |
---|---|
== | Equal to |
=== | Identical to |
!= | Not equal to |
!== | Not identical to |
~= | Pattern match |
> | Greater than |
< | Less than |
>= | Greater than or equal to |
<= | Less than or equal to |
Assignment Operators
Operator | Purpose |
---|---|
= | Assign |
+= | Addition |
-= | Subtraction |
*= | Multiplication |
/= | Division |
%= | Remainder |
&= | Bitwise AND |
|= | Bitwise Inclusive OR |
^= | Exclusive OR |
«= | Shift Left |
»= | Shift Right |
Logical Operators
Operator | Purpose |
---|---|
! | NOT |
&& | Logical AND |
|| | Logical OR |
Range Operators
Operator | Purpose |
---|---|
..< | Half-open range |
… | Closed range |
Bitwise Operators
Operator | Purpose |
---|---|
& | Bitwise AND |
| | Bitwise Inclusive OR |
^ | Exclusive OR |
~ | Unary complement (bit inversion) |
« | Shift Left |
» | Shift Right |
Overflow and Underflow Operators
Typically, assigning or incrementing an integer, float, or double past it’s range would result in a runtime error. However, if you’d instead prefer to safely truncate the number of available bits, you can opt-in to have the variable overflow or underflow using the following operators:
Operator | Purpose |
---|---|
&+ | Addition |
&- | Subtraction |
&* | Multiplication |
Example for unsigned integers (works similarly for signed):
|
|
Other Operators
Operator | Purpose |
---|---|
?? | Nil coalescing |
?: | Ternary conditional |
! | Force unwrap object value |
? | Safely unwrap object value |
Operator Overloading
Swift allows you to overwrite existing operators or define new operators for existing or custom types. For example, this is why in Swift you can join strings using the +
operator, even though it is typically used for math.
Operator overloading is limited to the following symbols, / = - + * % < > ! & | ^ . ~
, however you cannot overload the =
operator by itself (it must be combined with another symbol).
Operators can be specified as:
prefix
: goes before an object such as-negativeNumber
infix
: goes between two objects, such asa + b
postfix
: goes after an object, such asunwrapMe!
Custom operators
associativity
: defines how operators of the same precedence are grouped together (left, right)precedence
: gives some operators higher priority than others; these operators are applied first.
Refer Operator Declarations to see full details about operator associativity
and precedence
.
Example:
DefaultPrecedence group
|
|
Custom Precedence group
|
|
That’s it.
|
|
see also docs
Declaring Classes
Classes are typically declared using separate .swift
files, but multiple classes can also be created within the same file if you’d like to organize it that way.
Unlike Objective-C, there’s no need for an interface file (.h
) in Swift.
The implementation file should contain (in this order):
- Any needed
import
statements - A
class
declaration which contains any constants or variables necessary for the class - All public and private functions
Example:
MyClass.swift
|
|
Instantiation
When you want to create a new instance of a class, you use the syntax:
|
|
where x
and y
are variables that are passed in at the time of instantiation.
Declarations
More info here in the docs.
Preprocessor
Swift doesn’t come with a preprocessor so it only supports a limited number of statements for build time. Things like #define
have been replaced with global constants defined outside of a class.
Directive | Purpose |
---|---|
#if | An if conditional statement |
#elif | An else if conditional statement |
#else | An else conditional statement |
#endif | An end if conditional statement |
Imports
Directive | Purpose |
---|---|
import | Imports a framework |
Constants & Variables
Directive | Purpose |
---|---|
let | Declares local or global constant |
var | Declares a local or global variable |
class | Declares a class-level constant or variable |
static | Declares a static type |
Classes, Structure, Functions and Protocols
Directive | Purpose |
---|---|
typealias | Introduces a named alias of an existing type |
enum | Introduces a named enumeration |
struct | Introduces a named structure |
class | Begins the declaration of a class |
init | Introduces an initializer for a class, struct or enum |
init? | Produces an optional instance or an implicitly unwrapped optional instance; can return nil |
deinit | Declares a function called automatically when there are no longer any references to a class object, just before the class object is deallocated |
func | Begins the declaration of a function |
protocol | Begins the declaration of a formal protocol |
static | Defines as type-level within struct or enum |
convenience | Delegate the init process to another initializer or to one of the class’s designated initializers |
extension | Extend the behavior of class, struct, or enum |
subscript | Adds subscripting support for objects of a particular type, normally for providing a convenient syntax for accessing elements in a collective, list or sequence |
override | Marks overriden initializers |
Operators
Directive | Purpose |
---|---|
operator | Introduces a new infix, prefix, or postfix operator |
Declaration Modifiers
Directive | Purpose |
---|---|
dynamic | Marks a member declaration so that access is always dynamically dispatched using the Objective-C runtime and never inlined or devirtualized by the compiler |
final | Specifies that a class can’t be subclassed, or that a property, function, or subscript of a class can’t be overridden in any subclass |
lazy | Indicates that the property’s initial value is calculated and stored at most once, when the property is first accessed |
optional | Specifies that a protocol’s property, function, or subscript isn’t required to be implemented by conforming members |
required | Marks the initializer so that every subclass must implement it |
weak | Indicates that the variable or property has a weak reference to the object stored as its value |
Access Control
Directive | Purpose |
---|---|
open | Can be subclassed outside of its own module and its methods overridden as well; truly open to modification by others and useful for framework builders |
public | Can only be subclassed by its own module or have its methods overridden by others within the same module |
internal | (Default) Indicates the entities are only available to the entire module that includes the definition, e.g. an app or framework target |
fileprivate | Indicates the entities are available only from within the source file where they are defined |
private | Indicates the entities are available only from within the declaring scope within the file where they are defined (e.g. within the { } brackets only) |
|
|
Literals
Literals are compiler directives which provide a shorthand notation for creating common objects.
Syntax | What it does |
---|---|
"string" | Returns a String object |
28 | Returns an Int |
3.14 , 0xFp2 , 1.25e2 | Returns a Double object |
true , false | Returns a Bool object |
[] | Returns an Array object |
[keyName:value] | Returns a Dictionary object |
0b | Returns a binary digit |
0o | Returns an octal digit |
0x | Returns a hexadecimal digit |
Strings
Special characters can be included:
- Null Character:
\0
- Backslash:
\\
(can be used to escape a double quote) - Horizontal Tab:
\t
- Line Feed:
\n
- Carriage Return:
\r
- Double Quote:
\"
- Single Quote:
\'
- Unicode scalar:
\u{n}
where n is between one and eight hexadecimal digits
Multiline string literal
|
|
Array Access Syntax
|
|
Dictionary Access Syntax
|
|
Mutability
For mutable literals, declare it with var
; immutable with let
.
Functions
Declaration Syntax
Functions without a return type use this format:
|
|
class
precedes declarations of class functions:
|
|
static
is similar to class functions where you don’t need an instance of the class or struct in order to call a method on it:
|
|
Declare instance functions:
|
|
Function arguments are declared within the parentheses:
|
|
Return types are declared as follows:
|
|
You can have multiple return values, referred to as a tuple:
|
|
And those multiple return values can be optional:
|
|
By default, external parameter names are given when you call the function, but you can specify that one or more are not shown in the method signature by putting a _
symbol in front of the parameter name:
|
|
or you can rename the variable once within the method scope:
|
|
You can also specify default values for the parameters:
|
|
Swift also supports variadic parameters so you can have an open-ended number of parameters passed in:
|
|
And lastly, you can also use a prefix to declare input parameters as inout
.
An in-out parameter has a value that is passed in to the function, is modified by the function, and is passed back out of the function to replace the original value.
You may remember inout
parameters from Objective-C where you had to sometimes pass in an &error
parameter to certain methods, where the &
symbol specifies that you’re actually passing in a pointer to the object instead of the object itself. The same applies to Swift’s inout
parameters now as well.
Calling Functions
Functions are called using dot syntax: myClass.doWork()
or self.sayHelloToMyLilFriend("Rob Phillips")
self
is a reference to the function’s containing class.
At times, it is necessary to call a function in the superclass using super.someMethod()
.
Constants and Variables
Declaring a constant or variable allows you to maintain a reference to an object within a class or to pass objects between classes.
Constants are defined with let
and variables with var
. By nature, constants are obviously immutable (i.e. cannot be changed once they are instantiated) and variables are mutable.
|
|
There are many ways to declare properties in Swift, so here are a few examples:
|
|
Getters and Setters
In Objective-C, variables were backed by getters, setters, and private instance variables created at build time. However, in Swift getters and setters are only used for computed properties and constants actually don’t have a getter or setter at all.
The getter is used to read the value, and the setter is used to write the value. The setter clause is optional, and when only a getter is needed, you can omit both clauses and simply return the requested value directly. However, if you provide a setter clause, you must also provide a getter clause.
You can overrride the getter and setter of a property to create the illusion of the Objective-C property behavior, but you’d need to store them as a private property with a different name (not recommended for most scenarios):
|
|
Property Observer
Swift also has callbacks for when a property will be or was set using willSet
and didSet
shown below:
willset
: before assignmentdidSet
: after assignment
|
|
Lazy Property
lazy
: only compute once and remember the value, won’t re-compute if called again.
|
|
Accessing
Local Variables
Local variables and constants only exist within the scope of a function.
|
|
Naming Conventions
The general rule of thumb: Clarity and brevity are both important, but clarity should never be sacrificed for brevity.
Functions and Properties
These both use camelCase
where the first letter of the first word is lowercase and the first letter of each additional word is capitalized.
Class names and Protocols
These both use CapitalCase
where the first letter of every word is capitalized.
Enums
The options in an enum should be lowerCamelCased
Functions
These should use verbs if they perform some action (e.g. performInBackground
). You should be able to infer what is happening, what arguments a function takes, or what is being returned just by reading a function signature.
Example:
|
|
Closures
Closures in Swift are similar to blocks in Objective-C and are essentially chunks of code, typically organized within a {}
clause, that are passed between functions or to execute code as a callback within a function. Swift’s func
functions are actually just a special case of a closure in use.
Syntax
|
|
Examples
|
|
If the closure is the last parameter to the function, you can also use the trailing closure pattern. This is especially useful when the closure code is especially long and you’d like some extra space to organize it:
|
|
Capturing Values
A closure can capture constants and variables from the surrounding context in which it is defined. The closure can then refer to and modify the values of those constants and variables from within its body, even if the original scope that defined the constants and variables no longer exists.
In Swift, the simplest form of a closure that can capture values is a nested function, written within the body of another function. A nested function can capture any of its outer function’s arguments and can also capture any constants and variables defined within the outer function.
|
|
Swift determines what should be captured by reference and what should be copied by value. You don’t need to annotate a variable to say that they can be used within the nested function. Swift also handles all memory management involved in disposing of variables when they are no longer needed by the function.
Capturing Self
If you create a closure that references self.*
it will capture self
and retain a strong reference to it. This is sometimes the intended behavior, but often could lead to retain cycles where both objects won’t get deallocated at the end of their lifecycles.
The two best options are to use unowned
or weak
. This might look a bit messy, but saves a lot of headache.
Use unowned
when you know the closure will only be called if self
still exists, but you don’t want to create a strong (retain) reference.
Use weak
if there is a chance that self
will not exist, or if the closure is not dependent upon self
and will run without it. If you do use weak
also remember that self
will be an optional variable and should be checked for existence.
|
|
Reference: Apple: Automatic Reference Counting
Generics
Coming soon…
Control Statements
Swift uses all of the same control statements that other languages have:
If-Else If-Else
|
|
As you can see, parentheses are optional.
Ternary Operators
The shorthand notation for an if-else
statement is a ternary operator of the form: someTestCondition ? doIfTrue : doIfFalse
Example:
|
|
Nil Coalescing Operators
In Swift, we need to consider the use of optional
values. One very basic way to handle nil
cases is with an if-else
statement:
|
|
In this particular case, we are returning optionalValue
if it is not nil
, and "Empty"
if optionalValue
is nil
. The shorthand notation for this type of if(!=nil)-else
statement is a nil coalescing operator of the form: optionalValue ?? nonOptionalValue
Example:
|
|
For Loops
Swift enables you to use ranges inside of for
loops now:
|
|
Enumerating arrays & dictionaries
|
|
If you need to cast to a certain object type, see the earlier discussion about the as!
and as?
keywords.
While Loop
|
|
Repeat While Loop
|
|
Switch
Switch statements are often used in place of if
statements if there is a need to test if a certain variable matches the value of another constant or variable. For example, you may want to test if an error code integer you received matches an existing constant value or if it’s a new error code.
|
|
Switch statements in Swift do not fall through the bottom of each case and into the next one by default. Instead, the entire switch statement finishes its execution as soon as the first matching switch case is completed, without requiring an explicit break
statement. This makes the switch statement safer and easier to use than in C, and avoids executing more than one switch case by mistake.
Exiting Loops
Although break
is not required in Swift, you can still use a break
statement to match and ignore a particular case, or to break out of a matched case before that case has completed its execution.
return
: Stops execution and returns to the calling function. It can also be used to return a value from a function.break
: Used to stop the execution of a loop.
Extension
Extensions add new functionality to an existing class, structure, enumeration or protocol type
|
|
Protocol
Define
|
|
Usage
|
|
Protocol Extension
Protocols can be extended to provide method, initializer, subscript, and computed property implementations to conforming types.
Very Important and Useful: Implementation
to any method
or computed property
requirement of that protocol
can only be in extension
|
|
By creating an extension on the protocol, all conforming types automatically gain this method implementation without any additional modification.
You can use protocol extensions to provide a default implementation to any method or computed property requirement of that protocol.
|
|
Error Handling
Representing an Error
|
|
Passing Information
Coming soon…
User Defaults
User defaults are basically a way of storing simple preference values which can be saved and restored across app launches. It is not meant to be used as a data storage layer, like Core Data or sqlite.
Storing Values
|
|
Retrieving Values
|
|
There are also other convenience functions on UserDefaults
instances such as bool(forKey:...)
, string(forKey:...)
, etc.
Common Patterns
For a comprehensive list of design patterns, as established by the Gang of Four, look here: Design Patterns in Swift
Singletons
Singleton’s are a special kind of class where only one instance of the class exists for the current process. They are a convenient way to share data between different parts of an app without creating global variables or having to pass the data around manually, but they should be used sparingly since they often create tighter coupling between classes.
To turn a class into a singleton, you use the following implementation where the function name is prefixed with shared
plus another word which best describes your class. For example, if the class is a network or location manager, you would name the function sharedManager
instead of sharedInstance
.
|
|
Explanation: The static constant sharedInstance
is run as dispatch_once
the first time that variable is accessed to make sure the initialization is atomic. This ensures it is thread safe, fast, lazy, and also bridged to ObjC for free. More from here.
Usage: You would get a reference to that singleton class in another class with the following code:
|
|
Unicode Support
Although I don’t recommend this, Swift will compile even if you use emoji’s in your code since it offers Unicode support.
More info from Apple here
FileIO
C style FileIO
|
|
Swift Style FileIO
|
|