iOS Swift how to monitor UIViewController lifecyle - ios

I am new to iOS development. So pardon me if this is a very basic thing.
From what I have learnt till now:
UIViewController class resembles somewhat equivalent to an Activity class in Android.
and viewDidLoad/viewWillAppear method to onCreate/onStart method
and viewDidAppear method to onResume method
Please correct me if I am wrong here.
Now, in Android we can monitor which of these methods(including other lifecycle methods) are triggered/called by implementing an Interface (ActivityLifecycleCallbacks) (somewhat resembling a protocol in iOS) which exists in the Application class in any Activity (particularly in a class which extends Application class).
It means that now these methods will be triggered/called whenever there is any navigation from one screen to another in the android app.
How do I do this in iOS using Swift? How do I know which screen(UIViewcontroller) the user is currently in and where he is navigating?
In short I want to write a standalone class which logs which screen(UIViewController) the user is currently in and which one of the lifecycle methods(viewDidLoad, viewWillAppear etc) is being executed?
Someone please help me out.
Edit:- I don't want them to subclass my standalone class instead of UIViewController class.

There are no global events that are fired when the UIViewController lifecycle methods are called. To create those you would need to subclass UIViewController as has been suggested.
You can look at UIApplication.sharedApplication().keyWindow?.rootViewController to get the current root view controller (which is often, but not always the currently active view controller).
You wouldn't typically design an app that depended on some central object tracking the state of view controllers.
The flow of UIViewController methods is pretty well described in the class reference and you can also work it out from the function names -
viewDidLoad called after the view controller instance is loaded (once per instantiation)
viewWillAppear called before this view appears
viewDidAppear called after this view appears
viewWillDisappear called before this view disappears
viewDidDisappear called after this view disappears

Create a view controller subclass and add that implementation in there. Then make sure all the view controllers you create subclass that new class rather than UIViewController itself

Related

Calling a view controller class without popping up the view controller itself

I am upgrading my app version, hence needed to reduce two view controllers to one. Hence, I am calling the second view controller skipping the first one. But here I need to call the class of first view controller as there are some important declarations and implementations. How can I call first view controller's class without popping up its view controller.
This is confusing.
Why not taking all the initializing code from your first VC (copy-paste your properties, initialization in viewDidLoad etc.) to your second VC ?
Once you are done, get rid of the first VC as it is useless and make your second view controller the root.
A ViewController is meant to be "viewed", I suggest you don't just hide it, that's a really bad architecture.
If you don't need one view controller at all, then you can delete that View Controller from storyBoard, and also subclass your class as an NSObject class (lets call it DataProviderClass) instead of previously( UIViewController) subClass. It isn't a good idea to have a "dummy" view controller in a navigation Stack.
You can use your DataProviderClass class as a support file that can provide any data to your Second View Controller. And to perform calculations/methods in this class before launching your second VC, just run these methods in viewdidLoad method, by creating an instance of this NSObject class (DataProviderClass) and keeping a reference to it.
When you segue further, you can very easily even transfer the same reference of DataProviderClass.

Omit [super] call when overriding view events in UIViewController. Impact? [duplicate]

This question already has answers here:
What is meaning of calling superview's viewwillappear?
(3 answers)
Closed 9 years ago.
What happens if you don't call super in your implementation of the view events (viewWillAppear, viewDidAppear etc.) of UIViewController?
It seems like I've forgotten to do this before, and it's unclear to me that there was any adverse impacts.
If you subclass one of your own view controller classes, you will certainly want to call super for any of these types of methods or your own base class's methods will not be invoked.
There's also the question of whether your top-level view controller classes need to call super to run the code in the base UIViewController class itself. In the UIViewController reference, it appears that the requirement to call super is documented for certain methods, among them viewWillAppear:, viewDidAppear, viewWillDisappear:, and viewDidDisappear:
If you override this method, you must call super at some point in your implementation.
However, there is no indication of what will happen if you fail to do so.
So apparently, there is something implemented in these methods in the base iOS framework view controller classes. Or at least, Apple reserves the option to implement something in these methods. You could say that they are virtual rather than abstract methods.
If you've subclassed your UIViewController delegate from anywhere (and you always subclass UIViewController at least once, in making your customized view controller), then any delegate methods in subclasses you've derived from won't get called.

Objective-C: Inject code into delegate method

What I want
I want to add some logging code into my app without having to update all of my view controllers.
What I've tried
I attempted to add a category to UIViewController and override one of the delegate methods. However, this produced several warnings/errors.
Is there a way for me to inject code into all of my app's ViewControllers?
Look into method swizzling. It is a powerful tool and can save you a lot of time. Swizzle one of the methods you wish to have logs in, and then call the original method to have it do what it is originally supposed to.
You could subclass UIViewController and then add the logging methods in your super class. You would still need to touch all of your VC's though and change the class to your super class though.
You can't possibly have so many view controller classes in an iOS app that touching each one will be a huge problem. So create your own UIViewController subclass, maybe OurSuperViewController that'll act as a superclass for your view controllers, and add the logging there. Then modify each of your view controller classes so that they inherit from OurSuperViewController, and make sure that each one calls super in the relevant view controller methods.
Once you've done that, you can turn logging on or off at will by modifying just OurSuperViewController.

viewcontroller inheritance

I have 30+ viewcontroller in my project, and there is a behavior to be added in 28 of them.
When a button is clicked if 10 second not passed in that viewcontroller, I need to present a alertview sliding from top. (I have already implemented this behaviour for one of them)
But my question is, how can I inherit this behavior in a proper way for all of these viewcontrollers?
Googling this, but cannot find relavent solutions.
If all of your view controllers that need this functionality are subclasses of UIViewController, i.e. not UITableViewController or another subclass of UIViewController, you can create a subclass of UIViewController, say ButtonClickAlertViewController (or whatever makes sense) that implements the functionality you need to replicate. Then have all of the classes that need this functionality subclass your ButtonClickAlertViewController class instead of UIViewController.
You may need to take into account how this specific functionality integrates into each of your individual view controller classes. For example, you may need a method in your ButtonClickAlertViewController class that signals a button has been clicked in order to check your timer and possibly display an alert. In each of your classes that subclass ButtonClickAlertViewController, you might need to call this method in each of the IBAction methods that your button click actions call.
Subclass UIViewController and add your desired behavior for all view controllers and then subclass your existing view controllers from the viewController with the desired behavior.
Inheritance chain:
UIViewController -> ViewControllerWithBehaviorForAll ->
YouExistingViewlContollersWhichNeedTheBehavior

Accessing PageViewController's methods from child view controller

The issue is this. I have a PageViewController as my root view controller. Initialising the first page using SetViewControllers in the ViewDidLoad block of the PageViewController class works, as does the flipping back and forth of pages using the page's gesture recognizers. This root view controller is available application-wide via the AppDelegate.
I wanted to add the ability to return to the first page from anywhere in the book, so created a public method in my PageViewController class that simply called the SetViewControllers method. While this appears to work, I've noticed certain quirks. Music that is looping in the background (again, an AVAudio object declared in the AppDelegate) is restarted and the ViewDidLoad block doesn't fire until the page is turned again using the gesture recognizers.
I tried the same thing using GetNextViewController but that simply throws a null reference exception for the PageViewController reference. I'm assuming there is some relationship between the controls I'm not grasping, perhaps something to do with the PageViewController's DataSource. I have tried delegating this to a class that overrides the default methods, as well as using Mono's this.pageViewController.GetNextViewController = delegate(method signature) syntax to no avail.
Does anyone have any insights as to what my problem here is?
Edit: Code for AppDelegate.cs can be viewed here: https://gist.github.com/1747537 and for PageViewController.cs here: https://gist.github.com/1747559.
I can see several issues in your code:
your PageViewController is already the root controller in your app, there is no need to call AddSubview() anywhere.
You are inherinting from UIViewController and then encapsulate a UIPageViewController.You should either inherit from UIPageViewController or have no inheritance at all (if it is true as Dimitri says the UIPageViewController is not meant for subclassing).
The ReturnToFrontPage() could be a method of your AppDelegate instead of your subclassed UIPageViewController.
With your combination of inheritance and encapsulation you are building a hierachy of view controllers. This will make problems with events being triggered if not implemented properly.
In short: don't inherit anything in your case. Use a plain UIPageViewController and make the ReturnTpFrontPage() a method of your AppDelegate, then it should all be a walk in the park.

Resources