我有一个从 xib
文件启动的自定义 UIView
类。它具有名为 title
的实例属性,类型为 String?
。每当设置 title
属性时,UITextField
的文本都会更改为 title
属性的值。
如果 title
属性是存储属性,则程序按预期工作。
如果 title
属性是一个计算属性,那么程序会因 EXC_BAD_ACCESS
错误而崩溃,我认为这是因为 IBOutlet
还没有已初始化。
谁能解释为什么如果 title
是一个存储属性,它可以工作,但如果它是一个计算属性,它就会失败?
以下是源码——
NibView
是 UIView
的子类,负责 xib 文件的加载
class NibView: UIView {
override init(frame: CGRect) {
super.init(frame: frame)
loadNib()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
loadNib()
}
}
loadNib
方法的实现在一个扩展中
extension UIView {
func loadNib() {
guard let view = nib.instantiate(withOwner: self, options: nil).first as? UIView else { return }
view.frame = bounds
addSubview(view)
}
}
UIView
上的nib
属性的定义在另一个扩展中
extension UIView {
static var nib: UINib {
return UINib(nibName: String(describing: self), bundle: nil)
}
var nib: UINib {
return type(of: self).nib
}
}
下面的类是具有title属性的类。
class ProgressView: NibView {
var title: String? {
didSet {
titleLabel.text = title
}
}
@IBOutlet private weak var titleLabel: UILabel!
}
上面的类使用如下-
let view = ProgressView()
addSubview(view)
view.title = "Loading"
运行上面的代码会按预期工作。
但是,如果将 ProgressView
的实现更改为使用如下计算属性,则会失败
class ProgressView: NibView {
var title: String? {
get {
return titleLabel.text
}
set {
titleLabel.text = newValue
}
}
@IBOutlet private weak var titleLabel: UILabel!
}
谁能指出为什么 title
属性是计算而不是存储时的行为差异?
编辑 - 主线程崩溃并显示“Thread 1: EXC_BAD_ACCESS (code=EXC_I386_GPFLT)”
调用堆栈顶部的方法是“ProgressView.title.modify”。
编辑 2- 我不确定我做了什么,但在重新启动 xcode 后我无法重现该问题。即使使用计算属性,它也会按预期工作。
最佳答案
你的描述远非解释性的,但我猜测有一个 ProgressView nib,其中文件的所有者是一个 ProgressView,并且有一个从文件所有者到标签的 titleLabel
导出 Nib 内。 (我假设这是因为否则我无法解释您对 withOwner: self
的使用。)
基于该假设,我无法重现任何问题。你表达 title
的两种方式对我来说都很好。我放置了 print
语句以确保调用了正确的语句,确实如此;无论这是 didSet
还是计算属性的 setter,我们加载都很好,我看到了“正在加载”文本。
我的代码在 View Controller 的 viewDidLoad
中,如果有区别的话。
(顺便说一句,我怀疑您对 ProgressView()
的使用。这会导致 View 大小为零。这似乎没有任何区别,但这是个坏主意。标签是零尺寸 View 的 subview 。如果零尺寸 View 剪裁了它的 subview ,标签将是不可见的。即使零尺寸 View 不剪裁其 subview ,如果标签是一个按钮,按钮不会工作。零大小的 View 是一个坏主意。你应该给你的 ProgressView 一个真正的框架。)
关于ios - 当计算实例变量而不是存储实例变量时,行为会有所不同,我们在Stack Overflow上找到一个类似的问题: https://stackoverflow.com/questions/56406393/