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

时间:2015-01-25 12:41:22

标签: ios swift storyboard subclass xib

我试图理解如何正确地继承从Swift中的xib加载的视图。

我有TitleDetailLabel类,它是UIControl的子类。此课程有titleLabeldetailLabel个,UILabel s。

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 - 明细标签

在Storyboard中,我有视图控制器和占位符 - 带有约束的简单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。

提前致谢。

1 个答案:

答案 0 :(得分:1)

确保将.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方法,则不要在setupawakeFromNib中加载init:coder方法。

上述代码项目的完整答案是here或观看this video