1

我想将浮点范围映射到字符串。具体来说,我想转换风的度数方向,例如,在具有基本方向的相应字符串中:220 -> SW

Float可以使用自定义声明创建声明类型的计算属性,get以返回相应的String? 这样,我将其写为,Float但我将其读为String.

就像是:

var windDirection: Float? {
    get {
        switch self.windDirection {
        case 348.75..<11.25:
            return "N"
            break
        ...
        default:
            break
        }
    }
    set (newValue) {
        self.windDirection = newValue
    }
}

如果不是,我有什么可能产生相同的行为?

4

4 回答 4

2

据我所知,这是不可能的。计算属性仍然是只能是单一类型的属性。

也就是说,也许您最好为此拥有自己的类型:

struct WindDirection {
    var degrees: Float
    var stringValue: String {
        get {
            // compute the correct string here
            return "\(degrees)"
        }
        set {
            // compute the correct float value here
            degrees = Float(newValue) ?? 0
        }

    }
}

var windDirection: WindDirection

如果您不想使用自己的类型,那么您将不得不坚持使用 2 个不同的属性。

于 2016-12-12T12:43:10.367 回答
1

我想也许你可以像这样使用枚举

enum Wind {
    case degree(Float)
    case direction(String)
}

extension Wind {

    init?(degree: Float) {
        switch degree {
        case 11.25..<385:
            self = .direction("N")
        default:
            return nil
        }
    }

}

let wind = Wind(degree: 100) // Result is direction("N")
于 2016-12-12T13:33:04.980 回答
0

不要这样做!不要这样做!!永远不要这样做。我无法用言语来解释这是多么糟糕的想法。

private var _windDirection: Float?

var windDirection: Any? {
    get {
        guard let windDirection = _windDirection else {
            return nil
        }

        switch windDirection {
        case 348.75..<11.25:
            return "N"
        ...
        default:
            return nil
        }
    }
    set (newValue) {
        guard let windDirection = newValue as? Float else {
            _windDirection = nil
            return
        }

        _windDirection = windDirection
    }
}
于 2016-12-12T12:48:52.670 回答
0

(您应该看一下与 的一致性CustomStringConvertible,但对于技术讨论,以下是...)

但是,您可以实现一个enum包装器,其中每个案例包装不同类型的关联值(很像Optional<Int>wraps.none.some(Int))。

enum WindDirection {
    case asDegree(Float)
    case asString(String)
}

有了这个,您可以让您的实例变量windDirection成为两种不同包装类型的包装器,这将允许您在 setter 中期望一种包装类型并在 getter 中返回另一种包装类型。例如:

class Foo {
    private var _windDirection: WindDirection
    var windDirection: WindDirection {
        get {
            switch _windDirection {
            case .asDegree(let angle):
                switch(angle) {
                case 348.75..<360.0, 0..<11.25: return .asString("N")
                case 11.25..<33.75: return .asString("NE")
                /* ... */
                case _ : return .asString("Not expected")
                }
            case _ : return .asString("Not expected")
            }
        }
        set (newValue) {
            if case .asDegree(_) = newValue {
                _windDirection = newValue
            }
        }
    }

    init?(_ windDirection: WindDirection) {
        guard case .asDegree(_) = windDirection else { return nil }
        _windDirection = windDirection
    }
}

示例用法(但是,您需要在调用实例属性时处理包装的关联值的展开)

// attempt initialization
if let foo = Foo(.asDegree(11.0)) {

    // getter
    if case .asString(let windDirection) = foo.windDirection {
        print(windDirection) // N
    }

    // setter
    foo.windDirection = .asDegree(15.75)

    // getter
    if case .asString(let windDirection) = foo.windDirection {
        print(windDirection) // NE
    }
}
于 2016-12-12T13:20:01.423 回答