Last active
September 24, 2016 11:32
-
-
Save jhanzo/b2225cfbe1d2ccf7e6e3160f5a877935 to your computer and use it in GitHub Desktop.
Quick overview about value and reference types
This file contains bidirectional Unicode text that may be interpreted or compiled differently than what appears below. To review, open the file in an editor that reveals hidden Unicode characters.
Learn more about bidirectional Unicode characters
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