Skip to content

Instantly share code, notes, and snippets.

@jhanzo
Last active September 24, 2016 11:32
Show Gist options
  • Save jhanzo/b2225cfbe1d2ccf7e6e3160f5a877935 to your computer and use it in GitHub Desktop.
Save jhanzo/b2225cfbe1d2ccf7e6e3160f5a877935 to your computer and use it in GitHub Desktop.
Quick overview about value and reference types
import UIKit
//Let's have a look on Value and Reference Type in Swift 2.2
//What is the difference between value and reference types ?
//And what using such type implies on your code ?
//Swift blog inspiration : https://developer.apple.com/swift/blog/?id=10
//First, a short example about 'Int'
var a = 1
let b = a
print(a)//1
print(b)//1
a += 1
print(a)//2
print(b)//1
//so explanation is pretty simple
//and this is a little intro to ⭐️ Value Type ⭐️
//This type implies creating a COPY of object :
//Doing 'var b = a' means copy 'a' value in 'b'
//So let me introduce you ... ⭐️ Reference Type ⭐️
//it lets creating a reference between two objects :
class Bird {
var alive: Bool
init(alive: Bool) { self.alive = alive }
}
var eagle = Bird(alive: true)
var sparrow = eagle//Do you know evolution theory by Darwin ? 😜
print(eagle.alive)//true
print(sparrow.alive)//true
eagle.alive = false//Life is not fair :(
print(eagle.alive)//false
print(sparrow.alive)//false
//my two favorites birds are dead...
//indeed eagle and sparrow share the same instance and thus same property
//Ok right, now you know everything... Almost...
//Almost because there are others value and reference types to know
//... as structs, can you guess : value or reference type ?
struct Animal {
var alive: Bool = true
}
var dog = Animal()
var cat = dog
print(dog.alive)//true
print(cat.alive)//true
dog.alive = false//RIP my Brutus :(
print(dog.alive)//false
print(cat.alive)//true
//As you can see, in structs object are only and always COPIED as for Int type
//List of different value and reference types
// ----------------------//------------------------//
// Value // Reference //
// ----------------------//------------------------//
// Struct // Class //
// Int // subclasses of NSObject //
// Dictionnary (Struct) // //
// String (Struct) // //
// Array (Struct) // //
// ... // ... //
// Any without AnyObject // AnyObject //
// ----------------------//------------------------//
//Using struct and class is very common in swift, more than you can imagine
//Structs are a very used object in standard lib
//FYI: according to ray wenderlich blog there are 87 strucs, 8 enums, 4 classes occurences in swift lib (not iOS framework)
//An example of method for knowing what kind of type a variable is :
func printType <T: Any> (input: T) {
let type = T.self is AnyObject ? "reference" : "value"
print("\(input) is \(type) type")
}
//NB 1: reference instances compared with '==='
//NB 2: value types are compared with '=='
//sometimes on structs you would like to know if two instances are equal without comparing references
//A classic example :
struct Point {
var x: Double
var y: Double
}
let p1 = Point(x: 2.5, y: 3.5)
let p2 = Point(x: 2.5, y: 3.5)
//how do you do for comparing these 2 points ??
//print(p1 === p2)//will crash app !
//print(p1 == p2)//will crash app too !
//Solution : you have to implement equatable protocol
//Requirements operator : reflexive / transitive / symmetric
extension Point: Equatable { }
//don't put the following directly in protocol
func == (lhs: Point, rhs: Point) -> Bool {
return lhs.x == rhs.x && lhs.y == rhs.y
}
//and now you can do the same for all other value types of course !
print(p1 == p2)//true
//"And if I want to share multiple Point properties accross thread for comparing equality ?? 🤓"
//Damn it !! R you crazy dude ? What a strange idea you have ! ...
//... But be delightful, there is a solution !! ...
//... do you know a computer science notion named ⭐️ LOCK ⭐️ ?
//try to play a little with GCD for this let me give you some clues :
func synced(lock: AnyObject, closure: () -> ()) {
objc_sync_enter(lock)
closure()
objc_sync_exit(lock)
}
//get inspired ... 😎
//swift C API is very powerfull and a little bit tricky so if you are interested in,
//the following links should be a good starting point:
//https://www.uraimo.com/2016/04/07/swift-and-c-everything-you-need-to-know/
/////////////////////////////////
// DEEPER IN MEMORY MANAGEMENT //
/////////////////////////////////
//An excellent post talk about this subject deeper :
//https://www.raywenderlich.com/112029/reference-value-types-in-swift-part-2
//and official doc :
//https://developer.apple.com/library/content/documentation/Swift/Conceptual/BuildingCocoaApps/InteractingWithCAPIs.html#//apple_ref/doc/uid/TP40014216-CH8-XID_13
//so now I will try to sum up and give an overview of how swift really works
//FYI for printing mem addr
//for AnyObject : unsafeAddressOf(a1)
//for Any : ???? any suggestion ????
//As I said earlier Structs are always copied
//but actually memory mngmt is a little bit more tricky...
var a1 = Point(x: 10.0, y: 10.0)
var a2 = a1
var a3 = a2
//a1 > x: 10.0 ; y: 10.0
//a2 > x: 10.0 ; y: 10.0
//a3 > x: 10.0 ; y: 10.0
//ok right you know there are 2 copies of a1
//but actually, memory addr is exactly the SAME ! YES ! SAME MEM ADDR !!
a2.x = 5.0
//now :
//a1 > x: 10.0 ; y: 10.0
//a2 > x: 5.0 ; y: 10.0
//a3 > x: 10.0 ; y: 10.0
//and guess what : a1 and a3 still have same mem addr but no a2 ... not really surprised :(
a1.x = 5.0
//now :
//a1 > x: 5.0 ; y: 10.0
//a2 > x: 5.0 ; y: 10.0
//a3 > x: 10.0 ; y: 10.0
//but know guess !! come on !! 😎
//swift mem mngnt is enough smart to put same addr mem on a1 and a2, really nice isn't it
//You understand now why value types are so usefull ?!
//⭐️ Power of Structs ⭐️
Sign up for free to join this conversation on GitHub. Already have an account? Sign in to comment