在switch语句

时间:2017-12-04 13:35:44

标签: swift

我尝试使用切换案例来匹配通用类型,但我不确定如何匹配ImplicitlyUnwrappedOptional&#39>。

想象一下这个功能:

enum AttributeName: String {
    case someFloat = "someFloat"
    case someTint = "SomeTint"
}

func defaultValue<T>(_ name: AttributeName) -> T {
    switch name {
        case .someFloat:
            return CGFloat(8.0) as! T
        case .someTint:
            return UIColor.blue as! T
    }
}

func attribute<T>(_ name: AttributeName) -> T? {

    let attributes: [AttributeName: Any] = [AttributeName.someFloat: 10.0,
                                            AttributeName.someTint: UIColor.red]

    switch T.self {
    case is CGFloat.Type:
        guard let aFloat = attributes[name] as? Float
            else { return nil }
        return CGFloat(aFloat) as? T
    case is CGColor.Type:
        guard let color = attributes[name] as? UIColor
            else { return nil }
        return color as? T
    default:
        guard let attribute = attributes[name] as? T
            else { return nil }
        return attribute
    }
}


let button = UIButton()
button.layer.cornerRadius = attribute(AttributeName.someFloat) ?? defaultValue(AttributeName.someFloat)
button.backgroundColor = attribute(AttributeName.someTint) ?? defaultValue(AttributeName.someTint)
button.tintColor = attribute(AttributeName.someTint)

如果你试着打电话,上面的工作正常:

let button = UIButton()
button.layer.cornerRadius = attribute("float") // will be 10.0
button.backgroundColor = attribute("tint") // will be red

但是,尝试分配按钮tintColor将返回nil,因为T的类型将是ImplicitlyUnwrappedOptional<UIColor>。即:

button.tintColor = attribute("tint") // will be nil

我想我知道ImplicitlyUnwrappedOptional是什么以及为什么Apple使用它们(by reading this question)。但在这种情况下如何匹配tintColor

我可以:let tint: UIColor = attribute("tint")并将tint分配给按钮tintColor。 但是,手动创建UIColor并将其分配给tintColor真的是唯一的方法吗?

1 个答案:

答案 0 :(得分:0)

如何使用更好的类型来表示您的数据,回避您的问题?也许是这样的:

struct ButtonStyle {
    // If some of these proprties need to be optional (i.e. they're not always
    // set as part of a style) then comment below and I'll modify this accordingly
    cornerRadius: CGFloat
    backgroundColor: UIColor

    init(cornerRadius: CGFloat, backgroundColor: UIColor) {
        self.cornerRadius = cornerRadius
        self.backgroundColor = backgroundColor
    }

    // If you need to initialize ButtonStyle objects from dictionaries 
    // (e.g. from JSON), you can use this.
    // However, using `Codable` instead is ***greatly*** preferred.
    init?(fromDict dict: [String: Any] {
        guard let cornerRadius = dict["float"] as? CGFloat,
              let backgroundColor = dict["color"] as? UIColor {
            return nil
        }
        self.init(cornerRadius: cornerRadius, backgroundColor: backgroundColor)
    }
}

extension UIButton {
    var style: ButtonStyle {
        get {
            ButtonStyle(cornerRadius: self.layer.cornerRadius,
                        backgroundColor: self.backgroundColor)

        }
        set {
            self.layer.cornerRadius = newValue.cornerRadius
            self.backgroundColor = newValue.backgroundColor
        }
    }
}

let buttonStyle = ButtonStyle(cornerRadius: 10, backgroundColor: UIColor.red)
let button = UIButton()
button.style = buttonStyle