Logo Questions Linux Laravel Mysql Ubuntu Git Menu
 

Change the value that is being set in variable's willSet block

Tags:

swift

I'm trying to sort the array that is being set before setting it but the argument of willSet is immutable and sort mutates the value. How can I overcome this limit?

var files:[File]! = [File]() {     willSet(newFiles) {         newFiles.sort { (a:File, b:File) -> Bool in             return a.created_at > b.created_at         }     } } 

To put this question out of my own project context, I made this gist:

class Person {     var name:String!     var age:Int!      init(name:String, age:Int) {         self.name = name         self.age = age     } }  let scott = Person(name: "Scott", age: 28) let will = Person(name: "Will", age: 27) let john = Person(name: "John", age: 32) let noah = Person(name: "Noah", age: 15)  var sample = [scott,will,john,noah]    var people:[Person] = [Person]() {     willSet(newPeople) {         newPeople.sort({ (a:Person, b:Person) -> Bool in             return a.age > b.age         })      } }  people = sample  people[0] 

I get the error stating that newPeople is not mutable and sort is trying to mutate it.

like image 705
Mohsen Avatar asked Jan 07 '15 02:01

Mohsen


People also ask

Will set and did set?

willSet is called before the data is actually changed and it has a default constant newValue which shows the value that is going to be set. didSet is called right after the data is stored and it has a default constant oldValue which shows the previous value that is overwritten.

Did set and will set example?

These blocks of code are guaranteed to run whenever you update the variable. Thus you do not have to pay attention to it yourself. willSet { print("Name will change now.") } didSet { print("Name was changed.")}

What is property Observer in Swift?

Property observers observe and respond to changes in a property's value. Property observers are called every time a property's value is set, even if the new value is the same as the property's current value .


1 Answers

It's not possible to mutate the value inside willSet. If you implement a willSet observer, it is passed the new property value as a constant parameter.


What about modifying it to use didSet?
var people:[Person] = [Person]() {     didSet     {         people.sort({ (a:Person, b:Person) -> Bool in             return a.age > b.age         })     } } 

willSet is called just before the value is stored.
didSet is called immediately after the new value is stored.

You can read more about property observers here https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

You can also write a custom getter and setter like below. But didSet seems more convenient.

var _people = [Person]()  var people: [Person] {     get {         return _people     }     set(newPeople) {         _people = newPeople.sorted({ (a:Person, b:Person) -> Bool in             return a.age > b.age         })     }  } 
like image 130
rakeshbs Avatar answered Nov 11 '22 08:11

rakeshbs