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

Ale*_*rov 9 uitextview uiview ios 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)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

我想通过从"编码器"中提取帧大小可以暂时解决问题,但我没有找到它的关键.

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

Mar*_*n R 12

(从我上面的评论:)这看起来像一个Swift错误.initWithCoder:从Storyboard或Nib文件实例化视图(或视图控制器)时调用,并覆盖该方法在Objective-C中工作:

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

但等效的Swift代码

class BorderedTextView: UITextView {
    init(coder: NSCoder!) {
        super.init(coder: coder)
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

作为解决方法,您可以在中进行自定义初始化

override func awakeFromNib() {
    super.awakeFromNib()
    // ...
}
Run Code Online (Sandbox Code Playgroud)

Swift 1.2的更新:这显然已得到修复.参数已更改,它不再是隐式解包的可选项.因此,这将按预期编译和工作(使用Xcode 6.4测试):

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

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)

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

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

        // ...
    }
}
Run Code Online (Sandbox Code Playgroud)