Swift 2:在尝试读取时意外写入 属性
Swift 2: Unexpectedly writing to a property when trying to read it
我遇到的问题是我的 属性 的 willSet
和 didSet
被调用,即使我 只读 属性,这会破坏我的应用程序。
我把我的问题浓缩成了一个游乐场。取消注释 #1
以查看问题,或取消注释 #2
以查看预期的行为。
这是怎么回事?
protocol Departure
{
var line: String? { get }
}
class MyDeparture : Departure
{
var line: String? = "SomeString"
}
#if true
// #1: this causes a write to tableContet later (!)
typealias TableSection = (title: String, rows: [Departure])
#else
// #2: this doesn't cause a write to tableContent later
typealias TableSection = (title: String, rows: [MyDeparture])
#endif
var tableContent: [TableSection] = [ TableSection(title: "MySectionTitle", rows: [ MyDeparture() ]) ]
{
willSet { print("willSet tableContent") }
didSet { print("didSet tableContent") }
}
func getDepartureDescription() -> String? {
print("start getDepartureDescription")
defer { print("end getDepartureDescription") }
#if true
// writes to tableContent in case #1
let lineNumber = tableContent[0].rows[0].line
#else
// never writes to table content
let row = tableContent[0].rows[0]
let lineNumber = row.line
#endif
return "Your line is \(lineNumber)"
}
getDepartureDescription()
这会打印
start getDepartureDescription
willSet tableContent
didSet tableContent
end getDepartureDescription
我正在使用 Xcode 7 (7A218) 转基因种子。在 Xcode 6.4 和 Swift 1.2.
中一切都按预期工作
边注:
起初我认为运行时是——在阅读TableSection.rows
时——从分配给它的[MyDeparture]
数组创建一个新的[Departure]
数组。但即使以我能想到的最明确的方式更正它也没有解决问题:
// More correct types makes no difference:
var departures: [Departure] {
var result = Array<Departure>()
result.append(MyDeparture())
return result
}
var tableContent: [TableSection] = [ TableSection(title: "MyTitle", rows: departures ) ]
正在进行某种惰性初始化。只有当它到达第
行时
let lineNumber = tableContent[0].rows[0].line
那个运行时间好像是在填充数组的内容。
如果您将数组声明为包含符合 Departure
协议的元素,运行时间不知道 tableContent
的元素实际有多大,因为 classes和结构可以符合Departure
。因此,我认为它正在重新创建数组并错误地触发 didSet
和 willSet
。
我试过将您的协议限制为 classes,如下所示:
protocol Departure: class
{
var line: String? { get }
}
问题消失了,因为现在 运行时间知道数组只能包含 class 个引用。
我认为这是一个错误,您应该向 Apple 提出。
我遇到的问题是我的 属性 的 willSet
和 didSet
被调用,即使我 只读 属性,这会破坏我的应用程序。
我把我的问题浓缩成了一个游乐场。取消注释 #1
以查看问题,或取消注释 #2
以查看预期的行为。
这是怎么回事?
protocol Departure
{
var line: String? { get }
}
class MyDeparture : Departure
{
var line: String? = "SomeString"
}
#if true
// #1: this causes a write to tableContet later (!)
typealias TableSection = (title: String, rows: [Departure])
#else
// #2: this doesn't cause a write to tableContent later
typealias TableSection = (title: String, rows: [MyDeparture])
#endif
var tableContent: [TableSection] = [ TableSection(title: "MySectionTitle", rows: [ MyDeparture() ]) ]
{
willSet { print("willSet tableContent") }
didSet { print("didSet tableContent") }
}
func getDepartureDescription() -> String? {
print("start getDepartureDescription")
defer { print("end getDepartureDescription") }
#if true
// writes to tableContent in case #1
let lineNumber = tableContent[0].rows[0].line
#else
// never writes to table content
let row = tableContent[0].rows[0]
let lineNumber = row.line
#endif
return "Your line is \(lineNumber)"
}
getDepartureDescription()
这会打印
start getDepartureDescription
willSet tableContent
didSet tableContent
end getDepartureDescription
我正在使用 Xcode 7 (7A218) 转基因种子。在 Xcode 6.4 和 Swift 1.2.
中一切都按预期工作边注:
起初我认为运行时是——在阅读TableSection.rows
时——从分配给它的[MyDeparture]
数组创建一个新的[Departure]
数组。但即使以我能想到的最明确的方式更正它也没有解决问题:
// More correct types makes no difference:
var departures: [Departure] {
var result = Array<Departure>()
result.append(MyDeparture())
return result
}
var tableContent: [TableSection] = [ TableSection(title: "MyTitle", rows: departures ) ]
正在进行某种惰性初始化。只有当它到达第
行时let lineNumber = tableContent[0].rows[0].line
那个运行时间好像是在填充数组的内容。
如果您将数组声明为包含符合 Departure
协议的元素,运行时间不知道 tableContent
的元素实际有多大,因为 classes和结构可以符合Departure
。因此,我认为它正在重新创建数组并错误地触发 didSet
和 willSet
。
我试过将您的协议限制为 classes,如下所示:
protocol Departure: class
{
var line: String? { get }
}
问题消失了,因为现在 运行时间知道数组只能包含 class 个引用。
我认为这是一个错误,您应该向 Apple 提出。