5

I'm trying to override convenience init in UIAlertController, but it gives me an error like 'initializer does not override a designated initializer from its superclass'. How can I override it using inheritance or extension whatever? My codes are below.

import UIKit

class ColorAlertViewController: UIAlertController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }

    override convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
        super.init(title: title, message: message, preferredStyle: preferredStyle)
    }
}
RubyAn
  • 65
  • 2
  • 8

3 Answers3

4

you are not overriding any convenience init, it looks like you are creating a new one.

convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
    self.init(title: title, message: message, preferredStyle: preferredStyle)
}

Is probably what you want, you just need to handle the color code

Looks like you are going to have to go a round about way:

First create a create extension

extension UIAlertController
{

    class func create(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) -> AnyObject
    {
        return UIAlertController(title: title, message: message, preferredStyle: preferredStyle);
    }
}

Then in the ColorAlertViewController, you will create another function to create this object:

class func createWithColor(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?) -> AnyObject
{
    var c = super.create(title, message: message, preferredStyle: preferredStyle);
    //handle color code here
    return c;
}

Now anywhere you want to create this object, just call

var colorAlertView = ColorAlertViewController.createWithColor("title Name", message: "the message", preferredStyle: .ActionSheet, colorCode: "the color");

of course this won't work inside the UI builder, you would have to create this via code.

Knight0fDragon
  • 16,609
  • 2
  • 23
  • 44
  • 2
    This caused error: `Use of 'self' in delegating initializer before self.init is called` and `Self.init isn't called on all paths in delegating initializer`. – ljk321 Oct 13 '15 at 01:53
  • thank you ver much! you are my life saver! @skyline75489 we have to insert 'self.init()' above 'self.init(~~~~)' line. :D – RubyAn Oct 13 '15 at 01:59
  • looks like you can't do it in swift, weird it worked in the playground for me. https://developer.apple.com/library/prerelease/ios/documentation/swift/conceptual/swift_programming_language/Initialization.html – Knight0fDragon Oct 13 '15 at 02:06
  • @RubyAn Sorry, bro. `Override` seems to be a no-go. Perhaps you should consider this answer. – ljk321 Oct 13 '15 at 03:24
2

You really should be wrapping this inside a class and not overriding. That way your wrapper class can perform activities hidden from the caller.

Apple does clearly state that UIAlertViewController is not to be inherited from:

Important

The UIAlertController class is intended to be used as-is and does not support subclassing. The view hierarchy for this class is private and must not be modified.

Implementation:

extension UIAlertController
{
    class func create(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) -> AnyObject
    {
        return UIAlertController(title: title, message: message, preferredStyle: UIAlertController.Style.alert);
    }
}

class ColorAlertController {
    private var alertController: UIAlertController!

    private init() {
    }

    public convenience init(title: String?, message: String?, initialValue: T) {
        self.init()
        alertController = UIAlertController.createAlert(title: title, message: message)
        ... do color stuff ...
    }
}

The ColorAlertController can also include some modal presentation functions.

func present(inViewController controller: UIViewController) {
    controller.present(alertController, animated: true)
}

You can do some pretty cool things with wrapping UIAlertControllers inside custom modal controllers like this. The rest of the magic is up to you.

Peter Suwara
  • 781
  • 10
  • 16
0

There seems to be no way to do this "override".

According to this answer, it seems that you need to "override" the origin init before adding you custom init:

class ColorAlertViewController: UIAlertController {

    override func viewDidLoad() {
        super.viewDidLoad()
    }

    override func didReceiveMemoryWarning() {
        super.didReceiveMemoryWarning()

    }

    convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle) {
        self.init(title: title, message: message, preferredStyle:preferredStyle)
    }

    convenience init(title: String?, message: String?, preferredStyle: UIAlertControllerStyle, colorCode: String?){
        self.init(title: title, message: message, preferredStyle: preferredStyle)
        // handle colorCode
    }

}

This code has no compile error. However this cause infinite loop at runtime.

ljk321
  • 16,242
  • 7
  • 48
  • 60
  • Thanks for the reply. When I tried this code, it occurred exc_bad_access error. it looks like infinity calling init method. – RubyAn Oct 13 '15 at 02:06
  • Now I start to think that this might be a bug. – ljk321 Oct 13 '15 at 02:13
  • I updated my answer, it worked in the playground but it won't work in swift because convenience inits require a delegating init, so I posted a work around – Knight0fDragon Oct 13 '15 at 02:53
  • @Knight0fDragon The workaround is OK. Still I think that this is some kind of problem is Swift. `UIAlertController` does not have any designated initializer, which cause this problem. – ljk321 Oct 13 '15 at 03:09
  • I posted a link that explains it is intentional, look for this picture in the link on my answer: https://developer.apple.com/library/prerelease/ios/documentation/Swift/Conceptual/Swift_Programming_Language/Art/initializerDelegation01_2x.png Apple may not want UIAlertController to be subclassed with custom init, who knows. – Knight0fDragon Oct 13 '15 at 03:12
  • Yeah, I got the `chain` thing. But still, `UIAlertController` does not have any designated initializer for us to use. – ljk321 Oct 13 '15 at 03:14