直接或在字符串插值中使用时,字符串属性返回不同的值

时间:2018-07-30 03:22:11

标签: swift

我刚刚调试完一个情况,尽管有问题的字符串肯定包含一个值(它在打印前一行),但我的一些标签却没有显示任何文本。最终,我将其固定为根据访问字符串的方式返回不同的值。请注意,我不是正在寻找解决此问题的方法,我正在寻找导致这种行为发生的原因而我想念的原因。

我有一个带有以下可选字符串属性的协议,默认设置为nil

protocol SomeProtocol {
    var titleString: String? { get }
}

extension SomeProtocol {
    var titleString: String? {
        return nil
    }
}

这是在具有非可选字符串且在其他位置设置了title的类中实现的:

class SomeClass: SomeProtocol {
    var title: String
    var titleString: String {
        return title
    }
}

当尝试从SomeClass对象访问titleString的值时,无论nil属性如何,它总是返回title。可以通过将标签分配给以下内容来查看:

label.text = someClassInstance.titleString

但是,当我打印值或通过设置标签时

label.text = "\(someClassInstance.titleString)"

一切正常,并且显示了文本。

我将其来源缩小到用一个非可选属性覆盖了 optional 属性的位置。显然,当我直接访问该属性时,它是由协议实现返回的,而通过字符串插值使用该属性时,将返回类一。这种行为的真正背后是什么?

编辑:为演示此行为,请在Xcode游乐场中运行以下要点: https://gist.github.com/CaileanWilkinson/357c17f36d04b522b9bcf1241a825d9f

1 个答案:

答案 0 :(得分:3)

我觉得这有点类似于我的question的解决方案。在这个问题中,还有两个几乎相同的属性-一个是可选的,另一个是非可选的。而且我遇到过类似的情况,Swift无法弄清楚我想要哪个属性。

您在titleString中的SomeClass不会覆盖协议中的titleString属性。这反映在Xcode的建议中:

enter image description here

您可以像这样访问这两个属性:

someObject.titleString as String // accesses the one in SomeClass
someObject.titleString as String? // accesses the one in the protocol

我的意思是表达式的类型很重要。如果swift期望的表达式类型为String,则解析为SomeClass中的表达式。如果表达式的期望类型为String?,那么它将计算为协议中的表达式。

这说明了为什么在不使用字符串插值的情况下设置标签文本会调用协议中的属性(label.textString?,因此期望使用String?)以及为什么使用字符串插值会调用SomeClass中的属性(字符串插值应为非可选)。