在 CustomUIView 中覆盖 init() 会导致应用程序崩溃(EXC_BAD ACCESS)

Overriding init() in a CustomUIView crashes app (EXC_BAD ACCESS)

我正在尝试在 Swift 中子class 一个 UIView。

调用初始化程序时应用程序崩溃 (EXC_BAD_ACCESS) 的方式

这是class

class CustomActionSheet: UIView {
    private var cancelButtonTitle: String!;
    private var destructiveButtonTitle: String!;
    private var otherButtonTitles: [String]!;
 
    convenience init() {
        self.init();//EXC_BAD_ACCESS
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder);
    }

    convenience init(cancelButtonTitle: String!, destructiveButtonTitle: String!, otherButtonTitles: [String]!) {
        self.init();
    
    
        self.cancelButtonTitle = cancelButtonTitle;
        self.destructiveButtonTitle = destructiveButtonTitle;
        self.otherButtonTitles = otherButtonTitles;

        prepareUI();
    }

    func prepareUI() {
        //BLABLABLABLABLA
    }
}

我是这样称呼它的

var actionSheet: CustomActionSheet = CustomActionSheet(cancelButtonTitle: "Cancel", destructiveButtonTitle: "OK", otherButtonTitles: nil);

试图用 super.init() 替换 self.init() 但无法编译。

错误信息:

Must call a designated initializer of the superclass 'UIView'

Convenience initializer for 'CustomActionSheet' must delegate (with 'self.init') rather than chaining to a superclass initializer (with 'super.init')

你需要用一个框架初始化你的 UIVIew,即使它是零,你也需要覆盖 init 以便你可以在调用晚餐之前初始化你的变量:

class CustomActionSheet: UIView {
    private var cancelButtonTitle: String!;
    private var destructiveButtonTitle: String!;
    private var otherButtonTitles: [String]!;


    override init(frame: CGRect) {
        cancelButtonTitle = String()
        destructiveButtonTitle = String()
        otherButtonTitles: [String]()
        super.init(frame:frame)
    }

    required init(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder);
    }

    convenience init(cancelButtonTitle: String!, destructiveButtonTitle: String!, otherButtonTitles: [String]!) {
        self.init(frame: CGRectZero)
        self.cancelButtonTitle = cancelButtonTitle;
        self.destructiveButtonTitle = destructiveButtonTitle;
        self.otherButtonTitles = otherButtonTitles;
        prepareUI();
    }
}

注意我删除了你创建的其他便利初始化器,因为你所有的变量都是私有的,所以不需要这个初始化器,但是如果你想要一个空的初始化器,你可以添加为:

convenience init() {
    self.init(frame: CGRectZero)
}

也可以传递或修复框架的大小,您只需要进行适当的更改并调用 init(frame: yourFrame)

来自 Apple Documentation 的初始化规则:

Rule 1 A designated initializer must call a designated initializer from its immediate superclass.

Rule 2 A convenience initializer must call another initializer from the same class.

Rule 3 A convenience initializer must ultimately call a designated initializer.

A simple way to remember this is:

Designated initializers must always delegate up. Convenience initializers must always delegate across.

希望对你有帮助!