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

Deadly 提交于 2019-12-30 08:11:39

问题


I am trying to subclass a UIView in Swift.

Howver the app crashes (EXC_BAD_ACCESS) when the initializer is called

Here is the 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
    }
}

Here is how I call it

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

Tried to replace self.init() with super.init() but it won't compile.

Error Message:

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')


回答1:


You need to initializer your UIVIew with a frame, even if it is zero, you also need to override the init so you can initialize your variables before call supper:

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();
    }
}

Notice I remove the other convenience initializer you create given all your variables are private there is no need to this initializer, however if you want to have an empty initializer you can just add as:

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

Also the size of the frame can be passed or fix you just need to make the appropriate changes and call init(frame: yourFrame)

Rules for initialization from 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.

I hope that helps you!



来源:https://stackoverflow.com/questions/30798642/overriding-init-in-a-customuiview-crashes-app-exc-bad-access

易学教程内所有资源均来自网络或用户发布的内容,如有违反法律规定的内容欢迎反馈
该文章没有解决你所遇到的问题?点击提问,说说你的问题,让更多的人一起探讨吧!