更改变量的willSet块中设置的值

Moh*_*sen 25 swift

我正在尝试在设置之前对正在设置的数组进行排序,但参数willSet是不可变的并且会sort改变该值.我怎样才能克服这个限制?

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

为了将这个问题从我自己的项目环境中解决,我提出了这个要点:

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]
Run Code Online (Sandbox Code Playgroud)

我得到的错误说明这newPeople是不可变的,sort并试图改变它.

rak*_*hbs 32

改变里面的价值是不可能的willSet.如果实现willSet观察者,则将新属性值作为常量参数传递.


如何修改它使用didSet

var people:[Person] = [Person]()
{
    didSet
    {
        people.sort({ (a:Person, b:Person) -> Bool in
            return a.age > b.age
        })
    }
}
Run Code Online (Sandbox Code Playgroud)

willSet在存储值之前调用.
didSet在存储新值后立即调用.

您可以在此处阅读有关房产观察员的更多信息,请访问 https://developer.apple.com/library/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Properties.html

你也可以编写一个自定义的getter和setter,如下所示.但didSet似乎更方便.

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
        })
    }

}
Run Code Online (Sandbox Code Playgroud)

  • `didSet` 解决方案不是无限递归的定义行为吗? (2认同)
  • 在Swift4中didSet根本不是递归的。在Swift5中,如果像这样对'self'进行调用,则不是递归的,但是,如果您有一个变量也指向与'self'相同的实例,并在该变量上设置了属性,则*将*重新调用'didSet'。换句话说,Swift5仅在didSet内部直接针对self设置时才是非递归的。现在,以任何其他方式设置时都是递归的。 (2认同)

Jac*_*nce 6

在设置内部之前,无法更改值类型(包括数组)willSet.您将需要使用计算属性和后备存储,如下所示:

var _people = [Person]()

var people: [Person] {
    get {
        return _people
    }
    set(newPeople) {
        _people = newPeople.sorted { $0.age > $1.age }
    }
}
Run Code Online (Sandbox Code Playgroud)