子类内部的结构,分配给自身时解包可选
Struct inside subclass, unwrap optional when assigning to self
老实说,我找不到更好的标题了,所以如果有人能提出更有意义的建议,那就太好了。
前段时间我看到很棒的演讲 来玩吧:重构 Mega Controller! Andy Matuschak 的演讲。他展示了很好的模式:使用 struct 将数据注入视图,将视图的内部结构与视图控制器分离。
它是这样的:
class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}
var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}
}
现在如您所见,在 viewData
的 didSet
中,我们更新了 TaskTableViewCell
的 textLabel
和 detailTextLabel
。好吧,实际上是 UITableViewCell
因为它们都是继承的属性。
但这是基本的 table 视图单元格,我想要定制的东西。我已经添加了 someText
属性,并且需要初始化。现在,class 看起来如下:
class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}
var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}
var someText: String
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
someText = ""
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
当然我想更新 someText
,比方说用 ViewData
结构的 title
属性。
/// In didSet
someText = viewData?.title
这给了我以下错误:
TaskTableViewCell.swift:21:34: Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
这很奇怪,因为在 TaskTableViewCell
和 ViewData
中都没有可选的字符串。
我可以解决这个问题
someText = (viewData?.title)!
或者
someText = viewData!.title
但我想避免 force-unwrapping.
你能给我解释一下这是怎么回事吗?
以及为什么编译器在分配给继承 属性 时不打印错误?
但有一个可选的
someText
不是可选的,但 viewData
是
var viewData: ViewData?
,这就是你被迫解包的原因。
你可以这样避免:
someText = viewData?.title ?? "defaultValue"
//equivalent to
someText = viewData?.title == nil ? "defaultValue" : (viewData?.title)!
someText = viewData?.title
someText不可选,属性struct中的title不可选,但是struct viewData的实例是可选的,所以viewData的title是可选的。所以编译器会给出错误。
UILable 的属性 文本是可选的,默认值为零。所以
textLabel!.text = viewData?.title
可以。
老实说,我找不到更好的标题了,所以如果有人能提出更有意义的建议,那就太好了。
前段时间我看到很棒的演讲 来玩吧:重构 Mega Controller! Andy Matuschak 的演讲。他展示了很好的模式:使用 struct 将数据注入视图,将视图的内部结构与视图控制器分离。 它是这样的:
class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}
var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}
}
现在如您所见,在 viewData
的 didSet
中,我们更新了 TaskTableViewCell
的 textLabel
和 detailTextLabel
。好吧,实际上是 UITableViewCell
因为它们都是继承的属性。
但这是基本的 table 视图单元格,我想要定制的东西。我已经添加了 someText
属性,并且需要初始化。现在,class 看起来如下:
class TaskTableViewCell: UITableViewCell {
struct ViewData {
let title: String
let timingDescription: String
}
var viewData: ViewData? {
didSet {
textLabel!.text = viewData?.title
detailTextLabel!.text = viewData?.timingDescription.lowercaseString
}
}
var someText: String
override init(style: UITableViewCellStyle, reuseIdentifier: String?) {
someText = ""
super.init(style: style, reuseIdentifier: reuseIdentifier)
}
required init?(coder aDecoder: NSCoder) {
fatalError("init(coder:) has not been implemented")
}
}
当然我想更新 someText
,比方说用 ViewData
结构的 title
属性。
/// In didSet
someText = viewData?.title
这给了我以下错误:
TaskTableViewCell.swift:21:34: Value of optional type 'String?' not unwrapped; did you mean to use '!' or '?'?
这很奇怪,因为在 TaskTableViewCell
和 ViewData
中都没有可选的字符串。
我可以解决这个问题
someText = (viewData?.title)!
或者
someText = viewData!.title
但我想避免 force-unwrapping.
你能给我解释一下这是怎么回事吗?
以及为什么编译器在分配给继承 属性 时不打印错误?
但有一个可选的
someText
不是可选的,但 viewData
是
var viewData: ViewData?
,这就是你被迫解包的原因。
你可以这样避免:
someText = viewData?.title ?? "defaultValue"
//equivalent to
someText = viewData?.title == nil ? "defaultValue" : (viewData?.title)!
someText = viewData?.title
someText不可选,属性struct中的title不可选,但是struct viewData的实例是可选的,所以viewData的title是可选的。所以编译器会给出错误。
UILable 的属性 文本是可选的,默认值为零。所以
textLabel!.text = viewData?.title
可以。