Tuesday, June 16, 2015

strong, weak and unowned references in Swift

Both weak and unowned references do not create a strong hold on the referred object (a.k.a. they don't increase the retain count in order to prevent ARC from deallocating the referred object). But why two keywords? This distinction has to do with the fact that Optional types are built-in the Swift language.

A weak reference allows the possibility of it to become nil (this happens automatically when the referenced object is deallocated), therefore the type of your property must be optional - so you, as a programmer, are obligated to check it before you use it (basically the compiler forces you, as much as it can, to write safe code).

An unowned reference presumes that it will never become nil during it's lifetime. A unowned reference must be set during initialization - this means that the reference will be defined as a non-optional type that can be used safely without checks. If somehow the object being referred is deallocated, then the app will crash when the unowned reference will be used.





weak_unowned_ref.swift    Select all
// Optional Binding & chained class Person { var residence: Residence? init(residence:Residence?) { self.residence = residence } } class Residence { var address: Address? init(address:Address?) { self.address = address } } class Address { var buildingNumber: String? var streetName: String? var apartmentNumber: String? init(buildingNumber:String?, streetName: String?, apartmentNumber: String?) { self.buildingNumber = buildingNumber self.streetName = streetName self.apartmentNumber = apartmentNumber } convenience init() { self.init(buildingNumber:"", streetName:"", apartmentNumber:"") } } // Weak Reference with among objects independent lifetime class CreditCard { weak var holder: Person? } // Unowned references from owned objects with same lifetime class DebitCard { unowned let holder: Person init(holder: Person) { self.holder = holder } } let paul = Person(residence: Residence(address: Address(buildingNumber: "234", streetName: "Brooke Street", apartmentNumber: "9"))) //let paul = Person(residence: Residence(address: Address())) if let buildNumber = paul.residence?.address?.buildingNumber?.toInt() { println("paul's building number is \(buildNumber)") } if let buildNumber = DebitCard(holder: paul).holder.residence?.address?.buildingNumber?.toInt() { println("debitcard holder's building number is \(buildNumber)") } if let buildNumber = CreditCard().holder?.residence?.address?.buildingNumber?.toInt() { println("creditcard holder's building number is \(buildNumber)") } // Swift 3 syntax as below let paul = Person(residence: Residence(address: Address(buildingNumber: "234", streetName: "Brooke Street", apartmentNumber: "9"))) if let buildNumber = paul.residence?.address?.buildingNumber! { print("paul's building number is \(buildNumber)") } if let buildNumber = DebitCard(holder: paul).holder.residence?.address?.buildingNumber! { print("debitcard holder's building number is \(buildNumber)") } if let buildNumber = CreditCard().holder?.residence?.address?.buildingNumber! { print("creditcard holder's building number is \(buildNumber)") }




No comments: