Skip to content

Overview_Properties

Tom Ryan edited this page Jun 3, 2015 · 1 revision

Properties

There are several ways of providing custom behavior when getting or setting a property.


didSet

didSet executes additional operations after the property has been set.

struct MyDidSetStruct {
    var firstname : String
    var lastname : String? {
        didSet {
            println("Setting job description")
            self.jobDescription = "\(self.lastname!) has a job description"
        }
    }
    var jobDescription : String?
    init(firstname: String) {
        self.firstname = firstname
    }
}
var describedPerson = MyDidSetStruct(firstname: "Fred")
describedPerson.lastname = "Baxter"
describedPerson.jobDescription //"Baxter has a job description"

willSet

willSet executes operations before the property has been set.

struct MyWillSetStruct {
    var firstname : String
    var lastname : String? {
        willSet {
            self.lastname = "\(newValue) is a dork"
        }
    }
    var jobDescription : String?
    init(firstname: String) {
        self.firstname = firstname
    }
}
var describedPerson = MyWillSetStruct(firstname: "Fred")
describedPerson.lastname = "Baxter"
describedPerson.lastname! // "Baxter is a dork"

Lazy vars

struct MyLazyStruct {
    let firstname: String
    let lastname: String?
    lazy var fullname : String = {
        return "\(self.firstname) \(self.lastname!)"
    }()
}

Note that the above code is unsafe because it's unwrapping an optional (self.lastname!). This will crash at runtime if self.lastname is nil.


get and set full overrides

At times, it makes sense to fully override get and set. This can be useful when for example, the property will be loaded and saved as an NSUserDefault.

In this case, create a private var to store the value, and a public var for the additional operations.

Note: Fully custom get and set is much less preferable than leveraging didSet or willSet.

class MyUserController {
    private var _porpoise : Porpoise?
    var porpoise : Porpoise {
        get {
            if let user = self._porpoise {
                return user
            } else if let user = Porpoise.load() {
                return user
            } else {
                return Porpoise()
            }
        }
        set {
            self._porpoise = newValue
            Porpoise.save(self._porpoise!)
        }
    }
    init() {
        self._porpoise = Porpoise.load()
    }

    struct Porpoise {
        var firstname: String!
	
        static func load() -> Porpoise? {
        if let data = NSUserDefaults.standardUserDefaults().objectForKey("SavedUser") as! NSData?, dict = NSJSONSerialization.JSONObjectWithData(data, options: NSJSONReadingOptions.AllowFragments, error: nil) as? [String : AnyObject] {
            var firstname = dict["firstname"] as! String
            var person = Porpoise(firstname: firstname)
			
            return person
        } else {
            var porpoise = Porpoise()
            porpoise.firstname = "Unknown"
            return porpoise
        }
    }
        static func save(user: Porpoise) {
            //no-op for the purposes of this demo.
        }
    }
}