What Are the Fundamental Differences Between Set and Didset

What are the fundamental differences between set and didSet?

They do not do pretty much the same thing, on the contrary they have totally different purposes. The get and the set are used on computed properties. For instance, take this example structure that has no real use, but is a good demo.

struct test {
var x = 5
var y = 5
var number: Int {
get {
return x * y
}
set (newValue){
x = newValue / 2
y = newValue / 2
}
}
}

var s = test()
s.number //25
s.number = 100
s.x //50
s.number //2500

So, as you can see, the variable number isn't a variable in the traditional sense, it is a computed property. So, when I call s.number I get the product of x and y. Also, you would use the set to change other variables (not the computed property itself) in the structure. So, I set x and y to different values based on the newValue. This idea of a computed property can be used in place of a function and I find is very useful in simplifying retrieval of data from a function. For instance, you could have a structure that has a distance in kilometers and you might want that in miles very frequently. So, you could create a computed property miles for miles that computes the number of kilometers with the get method, and changes the number of kilometers with the setter if a you set miles to in your program.


Now, for the didSet and willSet. You can use these to notify your structure of a value change. For instance, an averageTracker.

struct averageTracker {
var total: Double = 0 {
didSet {
numEntries++
}
}
var numEntries: Double = 0
var average: Double {
get {
return total / numEntries
}
}
}

var ave = averageTracker()
ave.total += 10
ave.total += 20
ave.average //15

Notice how the didSet is actually on a variable that contains a value, that is, it is not a computed property. Also, I used a computed property average to get the average. Overall, I hope I cleared up your confusion regarding this very powerful aspect of Swift.

What is the difference between `didset` and `willset` in swift?

willSet is executed before property is set.

didSet is executed after property is set.

When to use set vs willSet in Swift?

set and willSet have two completely different purposes.

set is used similarly to setter methods in other languages, thus the programmer clearly knows why and when he wants/needs to use it.

willSet is comparable to a trigger. So, whenever the value will be set - and this could be outside of the programmer's influence - this function will be called (except for initializers as stated in other answers).

Imagine a public class that you have created and that you offer to other programmers as part of your framework.
Within a willSet you could trigger other functions (e. g. writing a log entry with timestamp), whenever the value will be set. In addition it allows you to take any actions before the value is set, e.g. saving the old value to somewhere else before it gets overwritten.

Of course, you could do everything I described within the set function without using willSet.

But willSet and didSet give you the opportunity to write code which is better readable:

  • do whatever you you need to do prior to setting the value in willSet
  • set the value in set
  • do whatever you need to to after having set the value (e.g. logging or cleaning up) in didSet

didSet vs willSet?

As Apple describes it:

You have the option to define either or both of these observers on a
property:

willSet is called just before the value is stored.

didSet is called immediately after the new value is stored.

So basically code performed in willSet will not have access to the newValue of the variable while it runs, whereas didSet will have access to it (since it's "after it's been set").

For :

var isCheckInDatePickerShown: Bool = false {
willSet{
print("This new value is: \(isCheckInDatePickerShown)")
}
}
var isCheckOutDatePickerShown: Bool = false {
didSet{
print("This new value after it was set is: \(isCheckOutDatePickerShown)")
}
}

if you call them:

print(isCheckInDatePickerShown)
.isCheckInDatePickerShown = true
print(isCheckInDatePickerShown)

Will print:

false

"This new value is: false"

true

print(isCheckOutDatePickerShown)
.isCheckOutDatePickerShown = true
print(isCheckOutDatePickerShown)

Will print:

false

"This new value after it was set is: true"

true

As you can see, the code ran in willSet did not yet have access to the new value, because it has yet to be committed to memory. Whereas didSet did have access to it.

What is the purpose of willSet and didSet in Swift?

The point seems to be that sometimes, you need a property that has automatic storage and some behavior, for instance to notify other objects that the property just changed. When all you have is get/set, you need another field to hold the value. With willSet and didSet, you can take action when the value is modified without needing another field. For instance, in that example:

class Foo {
var myProperty: Int = 0 {
didSet {
print("The value of myProperty changed from \(oldValue) to \(myProperty)")
}
}
}

myProperty prints its old and new value every time it is modified. With just getters and setters, I would need this instead:

class Foo {
var myPropertyValue: Int = 0
var myProperty: Int {
get { return myPropertyValue }
set {
print("The value of myProperty changed from \(myPropertyValue) to \(newValue)")
myPropertyValue = newValue
}
}
}

So willSet and didSet represent an economy of a couple of lines, and less noise in the field list.

What's the differences between `Combine` and `didSet` in Swift?

Sure, there are lots of ways to observe changes to data, KVO, Notification Center, didSet, combine etc, so in one sense these things are indeed similar. Differences though are:

a property can only have one didSet, which makes it hard for any number of observers to register an interest in the property.

But the big win with Combine is: a Combine pipeline allows you to create streams easily where you can say for example, transform the stream of changes to a stream that: observes changes to the user's input string, debounces it (rate limiting changes so we don't spam the server), filter those changes for any value that is at least 3 characters long, and that produces a new stream which you can observe. Map/FlatMap is also a really important combine operator, transform a stream of a's into a stream of b's. Also merging two streams together with combineLatest and so on, so you can take a stream of a's and stream of b's and make a stream of (a, b)'s and then map that to a stream of validated c's, for example.

What is the use of observer property didSet and willSet in Swift language?

The main usage is to capture and escalate the old and new values of the variable. willSet captures the newValue to which the property, variable, is about to be set and didSet captures the oldValue.

They're extremely handy for setup and teardowns... e.g.

var fileHandle: FileHandle {
willSet{
otherClass.disableAccessTo(handle: newValue)
}
didSet{
otherClass.enableAccessTo(handle: self.fileHandle)
yetAnotherClass.archiveFile(handle: oldValue)
}
}


Related Topics



Leave a reply



Submit