Swift:对UITextView或UICollectionView进行子类化并进行适当的初始化

时间:2014-06-29 14:38:37

标签: ios uiview uitextview swift

子类化UITextView(和UICollectionView)的问题是指定的构造函数是“initWithFrame”。但在现实生活中,当它从故事板加载时,将调用initWithCoder。

class BorderedTextView: UITextView {
    //will be called
    init(coder: NSCoder?){
       //constant values here is not an option
       super.init(frame: CGRectMake(0,0,100,100), textContainer: nil)
    }
    //will not be called
    init(frame: CGRect, textContainer: NSTextContainer!) {
        super.init(frame: frame, textContainer: textContainer)
    }
}

结果我无法在init上调用任何UI自定义代码,并为除默认值之外的Swift变量提供任何初始化值。

我认为通过从“编码器”中提取帧大小可以暂时解决问题,但我没有找到它的关键。

任何想法都比硬编码帧值好吗?

2 个答案:

答案 0 :(得分:12)

(来自我上面的评论:) 这看起来像是一个Swift错误。当initWithCoder:被调用时 视图(或视图控制器)从Storyboard或Nib文件实例化,并覆盖 该方法适用于Objective-C:

- (instancetype)initWithCoder:(NSCoder *)aDecoder
{
    self = [super initWithCoder:aDecoder];
    if (self) {
        // Initialization code
    }
    return self;
}

但等效的Swift代码

class BorderedTextView: UITextView {
    init(coder: NSCoder!) {
        super.init(coder: coder)
    }
}

失败并显示错误消息"必须调用超类的指定初始值设定项' UITextView'"。

UIView的所有子类都有此问题 他们自己的指定初始值设定项(例如UITextViewUICollectionView)。 另一方面,UILabel的子类不会出现问题 没有指定的初始化程序。 Swift语言对于调用超级课程非常严格。指定初始化程序, 但应该有一种方法可以覆盖所有自定义initWithCoder:子类的UIView,所以我认为这是一个Swift错误。

作为解决方法,您可以在

中进行自定义初始化
override func awakeFromNib() {
    super.awakeFromNib()
    // ...
}

更新Swift 1.2:这显然已得到修复。参数 改变了,它不再是一个隐式解包的可选项。所以这 编译并按预期工作(使用Xcode 6.4测试):

class BorderedTextView: UITextView {
    required init(coder: NSCoder) {
        super.init(coder: coder)

        // ...
    }
}

Swift 2(Xcode 7)的更新: init(coder:)是可用的 初始化程序现在:

class BorderedTextView: UITextView {
    required init?(coder: NSCoder) {
        super.init(coder: coder)

        // ...
    }
}

答案 1 :(得分:-1)

Swift 3的更完整答案:

class ValidatedTextField:UITextField, UITextFieldDelegate
{
    required override init(frame: CGRect)
    {
        super.init(frame: frame)
        //custom code
        self.delegate = self
    }

    required init?(coder: NSCoder)
    {
        super.init(coder: coder)
        //custom code
        self.delegate = self
    }