Swift - 保持两个属性同步

时间:2016-01-23 20:54:31

标签: swift properties synchronization

在Swift中,我有一个结构的两个相关属性,我想保持同步。

我目前正在与财产观察员这样做,但我必须添加一个额外的标志,以防止他们互相打乒乓球的无限游戏。

是否有更优雅和/或透明的方法来实现这一目标?

简化示例:

import Foundation

struct Angle {
    var blockPropertyObservers = false
    var degrees: Double {
        willSet(degrees) {
            print("will set degrees to \(degrees)")
            if !blockPropertyObservers {
                blockPropertyObservers = true
                radians = (degrees / 360) * 2 * M_PI
            } else {
                blockPropertyObservers = false
            }
        }
    }
    var radians: Double {
        willSet(radians) {
            print("will set radians to \(radians)")
            if !blockPropertyObservers {
                blockPropertyObservers = true
                degrees = (radians / (2 * M_PI)) * 360
            } else {
                blockPropertyObservers = false
            }
        }
    }
    init(inDegrees degrees: Double) {
        self.degrees = degrees
        self.radians = (degrees / 360) * 2 * M_PI
    }
    init(inRadians radians: Double) {
        self.radians = radians
        self.degrees = (radians / (2 * M_PI)) * 360
    }
}

理想情况下,我还想找到一种方法来避免在init()例程中复制转换代码......

1 个答案:

答案 0 :(得分:1)

你可以使用这两个中的一个的计算属性,让我们说度数。这将减少锅炉板代码,而不会丢失结构的功能。

struct Angle {
    var degrees: Double {
        get { return radians / (2 * M_PI) * 360 }
        set { radians =  (newValue / 360) * 2 * M_PI}
    }
    var radians: Double = 0.0

    init(inDegrees degrees: Double) {
        self.degrees = degrees
    }
    init(inRadians radians: Double) {
        self.radians = radians
    }
}

如果您不想每次都进行计算,可以将这两个属性声明为动态,并为它们设置后备存储:

struct Angle {
    private var _degrees: Double = 0.0
    var degrees: Double {
        get { return _degrees }
        set { _degrees = newValue; _radians = (newValue / 360) * 2 * M_PI }
    }

    private var _radians: Double = 0.0
    var radians: Double {
        get { return _radians }
        set { _radians = newValue; _degrees = radians / (2 * M_PI) * 360 }
    }

    init(inDegrees degrees: Double) {
        self.degrees = degrees
    }
    init(inRadians radians: Double) {
        self.radians = radians
    }
}