我正在使用 Swift 和 Xcode 6.4。
所以我有一个视图控制器,其中包含一些多个 UILabel 和 UIImageView 的组合。我想将 UILabel-UIImageView 组合放入自定义的 UIView 中,这样我就可以在前面提到的视图控制器中反复重用相同的结构。(我知道这可以转换为 UITableView,但是出于 ~学习~ 目的,请耐心等待)。这比我想象的要复杂得多,我很难弄清楚在 IB 中使所有内容正常工作的“正确”方法。
目前我一直在尝试使用 UIView 子类和相应的 XIB 文件,覆盖 init(frame:) 和 init(coder),从 nib 加载视图并将其添加为子视图。这是我在互联网上看到/阅读到的内容。(大约是这样的: http://iphonedev.tv/blog/2014/12/15/create-an-ibdesignable-uiview-subclass-with-code-from-an-xib-file-in-xcode-6)。
这导致了在 init(coder) 和从 bundle 加载 nib 之间产生无限循环的问题。奇怪的是,没有这些文章或以前在 stack overflow 上的答案提到这一点!
好的,所以我在 init(coder) 中添加了一个检查来查看子视图是否已经添加。这样就“解决”了这个问题,看起来是这样的。但是,当我尝试给自定义视图的 outlet 赋值时,我的自定义视图 outlet 却变成了 nil。
我使用了 didSet 并添加了断点来查看...他们确实被设置了一次,但是当我尝试修改标签文本颜色之类的东西时,那个标签却变成了 nil。我有点抓狂了。
可重复使用的组件似乎是软件设计 101,但我觉得苹果正在合谋对付我。我应该在这里寻找使用容器 VC 吗?我应该只嵌套视图并在主 VC 中拥有大量 outlet 吗?为什么这么复杂?为什么每个人的示例都对我无效?
期望结果(假设整个内容是 VC,方框是我想要的自定义 uiviews):
感谢阅读。以下是我的自定义 UIView 子类。在我的主 storyboard 中,我有设置了该子类作为其类的 UIView。
class StageCardView: UIView {
@IBOutlet weak private var stageLabel: UILabel! {
didSet {
NSLog("I will murder you %@", stageLabel)
}
}
@IBOutlet weak private var stageImage: UIImageView!
var stageName : String? {
didSet {
self.stageLabel.text = stageName
}
}
var imageName : String? {
didSet {
self.stageImage.image = UIImage(named: imageName!)
}
}
var textColor : UIColor? {
didSet {
self.stageLabel.textColor = textColor
}
}
var splatColor : UIColor? {
didSet {
let splatImage = UIImage(named: "backsplat")?.tintedImageWithColor(splatColor!)
self.backgroundColor = UIColor(patternImage: splatImage!)
}
}
// MARK: init
required init(coder aDecoder: NSCoder) {
super.init(coder: aDecoder)
if self.subviews.count == 0 {
setup()
}
}
override init(frame: CGRect) {
super.init(frame: frame)
setup()
}
func setup() {
if let view = NSBundle.mainBundle().loadNibNamed("StageCardView", owner: self, options: nil).first as? StageCardView {
view.frame = bounds
view.autoresizingMask = UIViewAutoresizing.FlexibleWidth | UIViewAutoresizing.FlexibleHeight
addSubview(view)
}
}
/*
// Only override drawRect: if you perform custom drawing.
// An empty implementation adversely affects performance during animation.
override func drawRect(rect: CGRect) {
// Drawing code
}
*/
}
编辑:以下是我目前已经得到的内容...
XIB:
结果:
问题:当尝试访问标签或图像输出时,它们是零。在检查所述访问断点时,标签和图像子视图都存在,并且视图层次结构与预期相同。
如果必须这样做,我可以全用代码来实现,但是我不太想用代码编写自动布局,因此如果有避免的方法,我宁愿不使用!
编辑/问题转移:
我找出了如何使输出停止为nil。
从这个SO回答中获得启示:Loaded nib but the view outlet was not set - new to InterfaceBuilder,除了赋值视图输出之外,我还分配了单个组件输出。
现在,这是我只是随便尝试了一下并看看它是否奏效的时候。有谁知道为什么我不得不这样做吗?这是什么黑魔法?