如何正确地子类化从 Swift 中的 xib 加载的视图类



我试图了解如何正确子类视图,该视图是从 Swift 中的 xib 加载的。

我有TitleDetailLabel类,它是UIControl的子类。此类具有titleLabeldetailLabel UILabel的插座。

class TitleDetailLabel: UIControl {
    @IBOutlet weak var titleLabel: UILabel!
    @IBOutlet weak var detailLabel: UILabel!
    override func awakeAfterUsingCoder(aDecoder: NSCoder) -> AnyObject? {
        return NTHAwakeAfterUsingCoder(aDecoder, nibName: "TitleDetailLabel")
    }
    func setTitle(text: String) {
        self.titleLabel.text = text
    }
    func setDetailText(text: String) {
        self.detailLabel.text = text
    }
}

XIB结构:

  • 占位符
    • 文件所有者:NSObject(未更改)
    • 第一响应者
  • 标题详细信息标签 - UIView - TitleDetailLabel
    • 标签 - UILabel - 标题标签
    • 标签 - UILabel - 详细标签

在故事板中,我有视图控制器和占位符 - 带有约束的简单UIView对象。

我已经为类创建了扩展UIView以简化与我感兴趣的对象的交换占位符。它适用于这个TitleDetailLabel类。下面是它的外观:

extension UIView {
    public func NTHAwakeAfterUsingCoder(aDecoder: NSCoder, nibName: String) -> AnyObject? {
        if (self.subviews.count == 0) {
            let nib = UINib(nibName: nibName, bundle: nil)
            let loadedView = nib.instantiateWithOwner(nil, options: nil).first as UIView
            /// set view as placeholder is set
            loadedView.frame = self.frame
            loadedView.autoresizingMask = self.autoresizingMask
            loadedView.setTranslatesAutoresizingMaskIntoConstraints(self.translatesAutoresizingMaskIntoConstraints())
            for constraint in self.constraints() as [NSLayoutConstraint] {
                var firstItem = constraint.firstItem as UIView
                if firstItem == self {
                    firstItem = loadedView
                }
                var secondItem = constraint.secondItem as UIView?
                if secondItem != nil {
                    if secondItem! == self {
                        secondItem = loadedView
                    }
                }
                loadedView.addConstraint(NSLayoutConstraint(item: firstItem, attribute: constraint.firstAttribute, relatedBy: constraint.relation, toItem: secondItem, attribute: constraint.secondAttribute, multiplier: constraint.multiplier, constant: constraint.constant))
            }
            return loadedView
        }
        return self
    }
}

我决定创建BasicTitleDetailLabel类的子类TitleDetailLabel以保留一些配置代码和其他东西。

class BasicTitleDetailLabel: TitleDetailLabel {
    override func awakeFromNib() {
        super.awakeFromNib()
        self.setup()
    }
    override init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        self.setup()
    }
    override init(frame: CGRect) {
        super.init(frame: frame)
        self.setup()
    }
    private func setup() {
        self.titleLabel.textColor = UIColor.NTHCadetGrayColor()
        self.detailLabel.textColor = UIColor.NTHLinkWaterColor()
    }
}

但是每次我将此占位符的类从 TitleDetailLabel 更改为 BasicTitleDetailLabel 后,应用程序都会崩溃。

应用程序崩溃,因为titleLabeldetailLabel为零。

我怎样才能在 xib 中正确使用这个TitleDetailLabel类以及如何正确地对其进行子类化?我不想创建另一个看起来与第一个使用子类相同的 xib。

提前谢谢。

确保将

.xib 文件的文件所有者设置为.swift文件。还要为根视图添加一个出口,然后从代码加载 xib。这就是我为类似项目所做的:

import UIKit
class ResuableCustomView: UIView {
    @IBOutlet var view: UIView!
    @IBOutlet weak var label: UILabel!
    @IBAction func buttonTap(sender: UIButton) {
        label.text = "Hi"
    }
    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        NSBundle.mainBundle().loadNibNamed("ReusableCustomView", owner: self, options: nil)[0] as! UIView
        self.addSubview(view)
        view.frame = self.bounds
    }
}

它与您的方法略有不同,但您可以添加init:frame方法。如果您有 awakeFromNib 方法,则不要在 awakeFromNibinit:coder 中加载 setup 方法。

我对上述代码项目的完整答案在这里或观看此视频。

最新更新