Ios 从超类UIView连接的IBoutlet仍然为零
我用笔尖工作。我有两个屏幕将使用具有相同行为的“相同”Ios 从超类UIView连接的IBoutlet仍然为零,ios,swift,xcode,iboutlet,Ios,Swift,Xcode,Iboutlet,我用笔尖工作。我有两个屏幕将使用具有相同行为的“相同”UIView组件。它不是同一个组件,因为在每个屏幕中我都放置了一个UIView,并进行了相同的配置,如图所示 为了解决这个问题并防止在其他类中复制相同的代码,我编写了一个类,即UIView子类,包含我需要的所有函数 之后,我将自定义类作为这些UIView组件的超类,以继承IBOutlets和所有函数 我的自定义类没有在Nib中定义,只是.swift类 我进行了所有必要的连接,但在运行时,IBOutlets是Nil 我的自定义类的代
UIView
组件。它不是同一个组件,因为在每个屏幕中我都放置了一个UIView
,并进行了相同的配置,如图所示
为了解决这个问题并防止在其他类中复制相同的代码,我编写了一个类,即UIView
子类,包含我需要的所有函数
之后,我将自定义类作为这些UIView
组件的超类,以继承IBOutlets
和所有函数
我的自定义类没有在Nib
中定义,只是.swift
类
我进行了所有必要的连接,但在运行时,IBOutlets
是Nil
我的自定义类的代码:
class FeelingGuideView: UIView {
@IBOutlet weak var firstScreen: UILabel!
@IBOutlet weak var secondScreen: UILabel!
@IBOutlet weak var thirdScreen: UILabel!
@IBOutlet weak var fourthScreen: UILabel!
private var labelsToManage: [UILabel] = []
private var willShow: Int!
private var didShow: Int!
override init(frame: CGRect) {
super.init(frame: frame)
self.initLabelManagement()
}
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initLabelManagement()
}
private func initLabelManagement() {
self.initLabelVector()
self.willShow = 0
self.didShow = 0
self.setupLabelToShow(label: labelsToManage[0])
self.setupLabels()
}
private func initLabelVector() {
self.labelsToManage.append(self.firstScreen)
self.labelsToManage.append(self.secondScreen)
self.labelsToManage.append(self.thirdScreen)
self.labelsToManage.append(self.fourthScreen)
}
private func setupLabels() {
for label in labelsToManage {
label.layer.borderWidth = 2.0
label.layer.borderColor = UIColor(hex: "1A8BFB").cgColor
}
}
func willShowFeelCell(at index: Int) {
self.willShow = index
if willShow > didShow {
self.setupLabelToShow(label: labelsToManage[willShow])
}
else if willShow < didShow {
for i in didShow ... willShow + 1 {
let label = labelsToManage[i]
self.setupLabelToHide(label: label)
}
}
}
private func setupLabelToShow(label: UILabel) {
label.textColor = UIColor.white
label.backgroundColor = UIColor(hex: "1A8BFB")
}
private func setupLabelToHide(label: UILabel) {
label.textColor = UIColor(hex: "1A8BFB")
label.backgroundColor = UIColor.white
}
}
当调用自定义类中的init()
时,IBOutlets
尚未连接
因此,我在父视图上创建了一个引用,并从viewdiload()
方法调用iniLabelManagement()
谢谢马特的帮助和耐心 问题在于以下代码:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
self.initLabelManagement()
}
问题是init(coder:)
现在谈论视图的出口还为时过早,这正是initLabelManagement
所做的;插座还没有接通。换言之:
required init?(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
}
override func awakeFromNib() {
super.awakeFromNib()
self.initLabelManagement()
}
我是如何得出这个答案的:
作为测试,我尝试了以下方法:
class MyView : UIView {
@IBOutlet var mySubview : UIView!
required init?(coder aDecoder: NSCoder) {
super.init(coder:aDecoder)
print(#function, self.mySubview)
}
override func awakeFromNib() {
super.awakeFromNib()
print(#function, self.mySubview)
}
}
以下是输出:
init(coder:) nil
awakeFromNib() <UIView: 0x7fc17ef05b70 ... >
init(编码器:)nil
awakeFromNib()
这证明了什么:
init(编码器:)
太快了;插座还没有接通
awakeFromNib
不是很快;插座已经连接好了
awakeFromNib
被调用,尽管您声称相反
也许init(coder:)
太早了:视图存在,但其出口尚未连接。在稍后的初始化时刻,例如覆盖willMove(toWindow:)
或didMoveToWindow
之前,尝试不访问视图出口。另外,我认为您声称的awakeFromNib
没有被称为非常令人不安,因为那是我本应该尝试的初始化时刻。非常感谢!这正是问题所在。在init中,插座尚未连接。我在viewDidLoad()
中调用了父类上的initLabelManagement()
func并工作。非常感谢。很好,但是您现在违反了视图类的封装。最好弄清楚视图本身何时可以保证其插座连接。这正是我所想的awakeFromNib
。谢谢,我会试试的。当我这样做时,我会将答案可视化。我添加了一个答案,证明应该调用awakeFromNib
,现在是开始讨论视图的出口的正确时机。setupLabels()
(来自initLabelManagement()
的消息)也适用于该层,在awakeFromNib()
中,哪一帧可能还没有计算出来。这不是应该在layoutSubviews()
或类似的东西上完成的吗?@AlejandroIván我关心的不是这个。OP询问在init(coder:)
中谈到outlet属性时,为什么在展开可选文件时出现“nil
错误,我回答了这个问题。这里所采取的整个方法的可取性不在本讨论的范围之内。
init(coder:) nil
awakeFromNib() <UIView: 0x7fc17ef05b70 ... >