I’ve been trying to learn some Swift lately (didn’t really learn/use it like properly properly) and I’m trying to document down some of my takeways or learning points. This is going to be a on-going and confusing document, but from time to time I will try to reorganise this.
enum is similar - they are both value type.
enum carry data too! but no stored properties; functions/computed props are fine.
class ?are reference type.
struct are stored on the stack,
classes are stored on the heap.
However, Swift has this thing called stack promotion, where
classes can be stored on the stack in the situation allows. So the above point is not always strictly followed. Smart swift!
structs are preferred in swift (https://developer.apple.com/documentation/swift/choosing_between_structures_and_classes), while
classes is only when required (e.g. need to be shared by many people or identity related).
structs are ‘faster’ compared to
classes since the cost of copying, alloc+dealloc, reference counting, is higher on
classes. Since it is also copy-on-write, (AFAIK) arrays and dictionaries are also copied but on reference level (i.e. still pointing to same data), but once you modify it, it then copies for real. Think of it as lazy/delayed copy, so actual duplication of array/dictionary data only takes effect when it actually happens. We don’t get this COW ‘feature’ for free with our own data types. Source: https://www.hackingwithswift.com/example-code/language/what-is-copy-on-write
Also in some situation, even
struct objects can be allocated to the heap or costs even more than a
class, e.g. a
struct (value type) having vars of
class (reference type) and we have copies of that
struct (causing more retain count on those vars of
struct conforms to a protocol it also has higher allocation costs.
There is no need for ‘new’, everything is as per above. i know this is counter-intuitive to what I learnt in cpp where
new = heap and non-
new = stack. Swift does everything for you based on value/reference type.
var (variable) and
let for consts, but in js/ts it’s
Also some recap:
- Objc/Swift uses ARC, automatic reference counting, which is an ownership system. Basically concept is like smart pointer in C++. Whenever something new reference the referenced object, the retain count of that referenced object is +1, and if they are set to nil, retain count is -1. Same in Objc, it has
strongconcept. If retain count is 0, that object is doomed to die. Because of the ownership system the one thing we need to take note of is 2 objects having a
strongreference to each other, causing the system to not know when to delete them since retain count is forever +1… When retain count is 0, any
weakreferences are zeroed out (i.e. set to
nil). In Swift, they also introduced
unowned, basically it’s a flavour of
weak, which I think it’s mainly used if you are sure the object you are referencing will not be zeroed out or app will crash (so it is more tightly coupled?). We should prefer to use
weakwhen it is not clear if the captured object will outlive our var/closure. - Apparently for weak references, this thing called
Side-Tablesentry is how the retain count are being tracked and
weakreference points to them (and not the actual object in the heap).
- It is also cool to know that the destruction of the reference object is not destroyed immediately - they have a life cycle too (live -> deiniting -> deinited -> freed -> dead), and depending on the
strongreferences that is left remaining that reference to it, the life cycle stage in which it is removed from memory differs. Source: https://www.vadimbulavin.com/swift-memory-management-arc-strong-weak-and-unowned/
More good resources:
Access level in swift. everything is
internal by default unless otherwise stated. Note
internal (default) ->
open. So if your
class is public, to prevent accidents, implicility your members are all still
internal. For unit testing, we can access up to
internal if we mark it as
@testable (not clear yet on how unit testing work). If we have a tuple of mixed access type, the most restrictive one will be set. And no, we cannot set access level for tuple.
Functions and methods are sometimes used interchangeably as both usable code and are defined by
func keyword, but in Swift, methods are functions that belong to a
enum only, and it has
self. Of course we want functions like
zip (which is like known/standard) but we wouldn’t want all our functions to be in the ‘public’ or ‘free’, since it’s like global(?) and polluting namespace(?).
Properties itself by definition are associated values for class/struct/enum.
Naming of properties
Swift has many kinds of properties it’s so confusing.. Seriously, please correct me if I am wrong.
First, variable vs property. This is basically same thing as the above functions/methods. They are all variables, but property is associated with class/struct/enum. Moving on.
Type Property -
struct-level properties (read:
static that we are used to).
Instance Property - the usual instance we are used to when we “
new” an object in the heap/stack.
Now, for each of the above, they can be further categorised:
Stored Property - the usual variable we are used to. Note that
enumcannot have stored property.
- This can also be further categorised: Lazy Stored Property (
varavailable only) - delay initialisation of the variable but multithreading can screw this up and init multiple times so need to beware!!!
- You thought that’s all? NO!! Stored Property is upgraded to be easier than Objective-C, now we can observe and react based on
didSetfunction. This is called Property Observer; they monitor changes and we can respond accordingly. You can access the
didSetin case you need it. More confusingly, if we are using this in a class situation, we can do it to our superclass and subclass too.
- This can also be further categorised: Lazy Stored Property (
Computed Property - basically think of it as a get function as they dont store property. counter-intuitively they also have a optional set function feature. Useful for e.g. computing a box’s center point given it’s origin and size on runtime. Like I said, getter/setter, but not good to go overboard with this, else just use it to call a function if it’s heavy.
- Hold up, the
didSetin Stored Property applies to us too, but only for subclass classes’s Computer Property… IKR…
- HOLD UP! Swift also introduced
sethere too, and you cannot reference itself inside the
setelse there will be stack overflow as it kept going into a loop forever. So they have some named parameter like
setto use, kind of like in Objective-C we used
_ivarXXXas the intermediate variable.
Property Observer - similar to Computer Property, TBC…
- Hold up, the
Needless to say,
static properties cannot access any instance variables/functions.
More random(?) info:
- If you
leta struct, you cannot change it’s properties even if they are
vars, but you can do it for
structis value type, when we mark the
structinstance itself as read-only, everything inside is read-only. Guess that make sense.
mutatingkeyword is for methods inside
structonly. Cos we want
structto be like immutable most of the time if possible but that’s not always possible. so we should treat mutating as a “red flag/warning” that could be potential for errors (which is the point of
struct, to prevent issues).
- In Swift,
Dictionaryare all value types.
Set, I don’t know.
initis clearer and easier than Objective-C’s. No value return or no
if (self)nonsense. Purely to init vars. For
structit is autogenerated unless you override it, for
enumtoo they have it. Property Observers are not called when we set directly the default value of the Stored Property or in our
- In Objective-C/C/C++, enums are 0 by default and ints only. In Swift, you set it to what you want,
String, and ‘autoconverting’ them by using the protocol like
Stringto direct convert to string when you
It is similar to Objective-C (I think), but in ObjC it is mainly used for delegates kind of usage. So protocols are new things in Swift, and many say Swift is more like a protocol-oriented programming, and that seems to be the case from what I seen so far.
enum can adopt protocols. Used it to separate (forgot what i wanted to say)
Protocols can inherit protocols too.
enum can implement multiple protocols.
We can use it as a type itself but it’s very rare. We also can’t use it for
For generics, we can use it like
struct MemoryGame<CardContent> where CardContent: Equatable.
We can also use Protocol to restrict extensions, so that the extensions only apply for certain scenarios.
Goold old C++ operator overloading has made a comeback in Swift.
https://github.com/FiveStarsBlog/WWDCNotes is really good website for reading a summary of what’s new in WWDC.
Last updated: 19th Sept 2021. Will keep adding as I learn.