24

While trying to implement an extension for UIViewController I realise that there is no normal way, or is not allowed to override this functions (even when they are available for UICollectionViewController and UITableViewController):

extension UIViewController{
  public override func viewWillAppear(){
    super.viewWillAppear()
    //do some stuff
 }
}

I realise that there is no normal way, or is not allowed to override this functions (even when they are available for UICollectionViewController and UITableViewController):

  • viewDidLoad
  • viewWillLoad
  • viewWillAppear
  • viewDidAppear

There is some way to do this? I would like to have some implementation there and working for every UIViewController on my app... All in just one place.

Please, note that I don't want to make a new class subclassing UIViewController, overriding those methods and making my controller to extend it. This is the obvious and simplest solution, but this do not satisfy what I'm trying to do.

I'm using swift 1.2 in XCode 6.3

Community
  • 1
  • 1
Hugo Alonso
  • 6,684
  • 2
  • 34
  • 65
  • 1
    Can you explain a little _why_ you want to do this? I guess what I mean is, since `viewDidLoad` etc. exist, and exist exactly in order for you to override them, and since one normally _does_ override them (because that is exactly what they are for), what _more_ do you want? – matt Apr 29 '15 at 18:52
  • I would like to have some stuff going on there, and going on for every UIViewController on my hierarchy. Lets say, I would like to check, for instance, if there is Connectivity every time I present a UIViewController. This is possible for UIViewCollectionController, so.. why not for UIViewController? – Hugo Alonso Apr 29 '15 at 18:59
  • 1
    "I would like to check, for instance, if there is Connectivity every time I present a UIViewController" Let me press you a little more. Why do you need to do that? Wouldn't it make more sense to check if there connectivity every time you _need_ connectivity? – matt Apr 29 '15 at 19:04
  • You see, I've been programming iOS for many years, and I've never had a problem knowing when my view controller's view loads, if I need to know that, because `viewDidLoad` is there to tell me. That's what a lifetime event _is_. So if there is something I need to know at that time, I can always find out. So it seems to me that there is no unsolved problem here. And since you have explicitly ruled out subclassing, I'm sort of left shrugging and wondering what you could possibly be asking. – matt Apr 29 '15 at 19:08
  • I'm implementing an amazon-like mechanism for when a view is loading and it loses connectivity in the process. I have a view that is appearing on top of my view, showing a button to retry. This view keeps in place after I go inside app's hierarchy and returns. What I want is to call a function that will ask my app to retry the request for data if this view is visible. As I said earlier, I can put this call on every viewWillAppear, but doing it that way seams a bit of ..dirty and I want a clean code. – Hugo Alonso Apr 29 '15 at 19:12
  • 1
    So one line of code repeated in every `viewWillAppear` is dirty? And alternatively, making every view controller a subclass of a common superclass which adds functionality to `viewWillAppear` is also dirty? So what would _not_ be dirty? Are you asking for the ability to modify the core functionality of UIViewController's own `viewWillAppear`? You can do that (because Objective-C's runtime is dynamic), but to me, _that_ is the dirty solution. – matt Apr 29 '15 at 19:16
  • 1
    Still, you might want to read e.g. this if you're curious: http://stackoverflow.com/questions/5339276/what-are-the-dangers-of-method-swizzling-in-objective-c – matt Apr 29 '15 at 19:19
  • this is a great question, @HugoAlonso. I just don't know the best way to abstract this out. – Fattie May 16 '16 at 19:15
  • HI @JoeBlow, as extensions are like an appendix to your class implementation this can not be done. **override** is *only for when subclassing*, and extensions are **not** below in the hierarchy but *actually parallel* to the implementation of the class. – Hugo Alonso May 16 '16 at 19:41
  • hi @HugoAlonso - did you mean to address me; I did not say it could be done with an Extension (it cannot, as you say). {Someone below said that in general you should not use Extensions often in Swift. I replied that you should use extensions everywhere in Swift!} – Fattie May 16 '16 at 19:49
  • regarding Extensions, and the problem you raise in this question. extensions can surely help you *make the code look much tidier*. The extra work that you have to do, relating to Amazon, in the `viewDid` methods: you could reduce it all to one line of code using extensions; this would be then be incredibly easier to place in all the classes which need it. – Fattie May 16 '16 at 19:51

1 Answers1

25

What you are trying to do is similar to what done by this code:

class MyClass {
    func myFunc() {}
}

extension MyClass {
    override func myFunc() {}
}

The 4 methods that you are trying to override are defined in UIViewController, and not to one of its superclasses. And you can't override a method which is defined in the same class.

Update

I can think of 2 different ways to solve the problem - the first is the one you don't want (subclassing UIViewController).

The other one is method swizzling - I never used it so I don't want to provide you inaccurate info. Maybe it's worth reading this article by Nate Cook, which incidentally is showing an example of replacing viewWillAppear.

Antonio
  • 71,651
  • 11
  • 148
  • 165
  • @Antonio I'm new on swift so could you tell me what's the purpose or advantage for using extension ? For example why putting tableview dataSource in extension not directly in my class ? – Chlebta Nov 05 '15 at 07:38
  • @Chlebta That's usually done for having cleaner code. I usually use Extensions when implementing delegates, so one extension per implemented delegate. Don't use them everywhere, that's an Anti-Pattern again. – Frederik Winkelsdorf Mar 02 '16 at 11:45