Megool
Megool

Reputation: 999

Method overriding in swift

Basically I am currently adding functionX to everywhere i present an UIAlertController as seen below:

let alert = UIAlertController(title: "", message: "", preferredStyle: .alert)
let okAction = UIAlertAction(title: "ok", style: .default)
alert.addAction(okAction)
functionX(actionSheet: alert, controller: self)
self.present(alert, animated: true, completion: nil)
// or it can be
// tableviewController.present(alert, animated: true, completion: nil)

Instead of calling functionX every time, I want to override a present method and call functionX there. I attempted the following:

extension UIViewController {
    override func present(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if (viewControllerToPresent is UIAlertController) {
            functionX(actionSheet: viewControllerToPresent, controller: /* what should this be? */ )
        }
        super.present() //error here
    }
}

Is this an appropriate approach? Can you help me fill the missing parameters?

i.e.:

Upvotes: 0

Views: 904

Answers (3)

Isaaс Weisberg
Isaaс Weisberg

Reputation: 2823

Overrides of NSObject's derivatives in Swift's static extensions is only for Objective-C compatibility. You cannot override in extensions of pure Swift declarations. Think of it in such manner that if the class itself adds an override, and then a static extension adds an override. Which implementation should the linker link? And which implementation does super call refer to? In Objective-C this behavior is undefined, in Swift the extension override is ignored all together.

What you could do instead is move the overriding function from the extension directly to the class.

Upvotes: 0

Sweeper
Sweeper

Reputation: 275085

According to the Swift guide,

Extensions can add new functionality to a type, but they cannot override existing functionality.

So you shouldn't really be overriding an existing method in a UIViewController in an extension.

What you could do is, to add your own present, called functionXAndPresent:

extension UIViewController {
    func functionXAndPresent(_ viewControllerToPresent: UIViewController, animated flag: Bool, completion: (() -> Void)? = nil) {
        if (viewControllerToPresent is UIAlertController) {
            // to answer your second question, you should use "self" here
            functionX(actionSheet: viewControllerToPresent, controller: self)
        }
        present(viewControllerToPresent, animated: flag, completion: completion)
    }
}

You can't do this by overriding because as you have found out, you can't really refer to the "non-overridden" method at the end. super.present doesn't work because you are in an extension, not a subclass.

Upvotes: 4

PGDev
PGDev

Reputation: 24341

You can simply create a common method showAlert(with:and:) in a UIViewController extension and call functionX when the alert is presented, i.e.

extension UIViewController {
    func showAlert(with title: String?, message: String?) {
        let alert = UIAlertController(title: title, message: message, preferredStyle: .alert)
        let okAction = UIAlertAction(title: "OK", style: .default)
        alert.addAction(okAction)
        self.present(alert, animated: true, completion: {
            self.functionX(actionSheet: alert, controller: self)
        })
    }

    func functionX(actionSheet: UIAlertController, controller: UIViewController) {
        //your code here...
    }
}

Usage:

Call the showAlert(with:and:) method from whatever controller you want to, be it a UIViewController or a UITableViewController or any other, i.e

self.showAlert(with: "Alery..!!!", message: "This is a sample alert.")

Upvotes: 1

Related Questions