iOS Development With Swift Part 4
Contents
This is part 4 of the swift iOS Programming tutorials series. The first part of the series is here and the previous part of the series that is tutorial # 3 is here. In the previous tutorial we had added button to start recording with an image of microphone, added text to show when recording is in progress and finally added a button to stop the recording. We also worked with actions and outlets and learned how to add constraints to view elements. Recording the audio will come in later tutorial in the series for now we will learn how to move to another scene which will have the layout for playing audio in different ways.
View Lifecycle
Right now initially we see both the record button and the stop button when the app starts but it does not make sense to have the stop button showing when app first time loads as we have not pressed the stop button yet. So we need to correct that somehow to hide the stop button when the app loads. We know that the code we will write will be somewhere in ViewController.swift but we need to think about in which function and at what stage we will add the code to hide the stop button. That is where the view lifecycle comes in.
Each application goes through different stages when the app first starts or ends. At each stage a different function of UIViewController is called. Different stages are suitable for different type of tasks and we will learn next what is the view lifecycle and what each stage does.
- You can notice that our view controller class inherits from UIViewController as you can see in this line of our ViewController.swift
1
class ViewController: UIViewController
- This above line basically says that our class inherits from UIViewController and there are some view lifecycle functions which we inherit from ui view controller which we can use.
- First think of the answer where you should write the code to hide the stop button, use google or look in the documentation to understand the life cycle and where you should put the code. Once you think you got the answer check out the swift forums for read what others have discovered or share your thoughts.
- I hope you have thought about the answer and shared your thoughts so let me now tell you the answer.
- As already as i have mentioned each view controller which inherits from uiviewcontroller goes through different stages and you can read more about the different stages in this stack overflow link or this nice diagram shared by Udacity instructor. Once you have looked at the resources look at the description below to understand each stage.
View Life Cyle Stages
- viewDidLoad: This function is called the first time the controller class is created. Once the controller class is created and completes loading this function is called. This function is called before the view even appears. This function is normally is very suitable if you want to do some initial setup or one time tasks for a view controller. This function is only once in a view controller life cycle. One thing to note is as the view at this time has not loaded you cannot access any outlets and should not try to update the view at this point. It is even possible that this function is called but the view never loads.
- viewWillAppear: This function is called before the view actually appears. After executing this function the view will appear on the screen. At this stage you have access to your outlets and you can change view elements. This is a good stage to synchronize the view based on the state of the model or make sure that all the view button states and all the view elements are in the correct state. You should not put time-consuming tasks at this stage and only put code which needs to be executed before the view loads. This function is called every time a view comes to the screen so this function called be multiple times in a view controller lifecycle. For example if a view first times loads viewDidLoad is called once and viewWillAppear is called and other functions are called which we will discuss and the view goes off screen. Now if the view is only hidden and then comes back on screen then viewDidLoad will not be called but as the view is re-appearing viewWillAppear will be called so put things which are related to view appearing over and over again in this function.
- viewDidAppear: This function is called once the view has appeared on the screen. At this point you can start any animations or start a thread to retrieve data from some service.
- viewWillDissappear: This function is called just before the view is about to go off screen i.e. the view is about to be hidden or destroyed. This is a counter function to viewDidAppear and is a good place to stop any running animations. Also, you should save the state of the controller you want to at this stage or commit any unsaved changes. You still have access to outlets and state of the view so use that to save the state of the controller at this point.
- viewDidDissappear: This function is called once the view has been hidden from the screen. At this stage the view has already disappeared from the screen and you don’t have access to any state.
- viewWillUnload/viewDidUnload: These function used to be called just before the controller class was completely destroyed and you used to destroy any memory or references at this point but these functions are now deprecated since iOS 6 and memory/view no longer need to be cleaned up and you don’t need to use these functions anymore. Chances are you won’t need to use these functions anymore as there is no cleanup needed in iOS 8.
Where to add the code?
Now we know about the view lifecycle we can actually tackle the problem of where to hide the stop button.
- We could put our code in viewDidLoad but the problem is that viewDidLoad will only be called once when the class is created and in our case when we will press the stop button to stop the recording we will see another screen and we can return from that screen back to the main recording screen so the second time viewDidLoad will not be called so we can remove viewDidLoad as an option. Also viewDidLoad is only used for one time setup and that time we don’t have access to view elements and outlets.
- The only option that makes sense is viewWillAppear function as that will be called every time the view is about to be shown on the screen and is the perfect place to show/hide any view elements and at this moment we have access to outlets as well so we should write our code to hide the stop button in viewWillAppear.
Hiding The Stop Button
Now let’s actually implement the change.
- First go to ViewController.swift file and you will see that right now viewWillAppear is not present anywhere in code. As viewWillAppear is defined in UIViewController and we inherit from this class we can choose to override and implement viewWillAppear in our function.
- So beneath the viewDidLoad function start typing viewWillAppear and XCode will help you autocomplete. Press the autocomplete entry for viewWillAppear and you should see a similar function as given below
1 2 3
override func viewWillAppear(animated: Bool) { }
- The override keyword tells XCode that we are overriding the function in this class defined in the super class. The advantage of using override is that XCode actually makes sure that the super class actually has the function we are trying to override and gives an error if no such function exists.
- Good we have our function but wait how do we hide the stop button we don’t have any way to access the stop button right now. The answer is we need to make a outlet from our storyboard stop button to our controller like we did for the recording label.
- First open up storyboard and turn on assistant editor so the view is on the left side and our code on the right side.
- Now first select your stop button and press and hold down control keys and move your mouse starting from the stop button to the code beneath the recording label. XCode will help you show by showing text to insert Outlet. When you see the text release the mouse button and a pop up will appear.
- We have already done similar steps for recording label so first make sure that the type is outlet and in the name enter stopButton
- Now go back to viewWillAppear function and enter the following line:
1
stopButton.hidden = true
- Now we need to show the stop button when we press the record button so in recordAudio function add the following line to show the stop button.
1
stopButton.hidden = false
- Now run the app, initially the stop button should be hidden. Press the record button and the stop button should appear now along with the recording label.
Exercise
Now in order to make sure you understand the view life cycle it is better you do an exercise. Suppose you have a screen A which has a button in the middle of the screen. When you press the button in screen A the scene changes to screen B. Screen B has a back button. You press that button and the screen B is now hidden and you can view again screen A.
- For this scenario fill out the handout provided by Udacity instructor which can be download here
- Next, once you have filled out your answer share your diagram and experience on udacity forum thread and discuss with other people if you have any question/confusion.
- This is a good exercise to make sure you understand the life cycle.
Disable Record Button
There is still one problem that once you click on the record audio button the record button is still active and we can accidentally press the button again. This is not the correct thing because once we start recording we can only stop the record by using the stop button and the record button should not work till we have finished recording the last audio. So let’s disable the record button when we have clicked it once and enable it when view appears.
- First we will need access to the record button so make an outlet for the stop button dragging from the microphone button to the code.
- Name the outlet recordButton
- In order to disable the recordButton we will have to use the enabled property for the button. This property is by default set to true to denote that the button is active and we will set it to false to disable the button.
- Add the following code in recordAudio function
1
recordButton.enabled = false
- This will dim the recording button when it is pressed and disable any further clicking of the record button.
- Now we need to enable this also. As right now when we will press the stop button we will move to another screen and when we return to the recording screen the record button should be active a good place to enable the record button is in viewWillAppear. In viewWillAppear add the following code to enable the button
1
recordButton.enabled = true
- Now run the app and test it out. Initially the record button should be active. When we click the record button the record button becomes greyed out and we can’t press it again. Once we will implement the next scene we will be able to see the button enabled again but for now trust me that the code is correct.
Adding a new Scene
Now let’s add a new scene. What we need to do is when we press the stop recording button to stop the recording we will need to save the audio file, change the screen to show 4 buttons to play the audio file in different ways as discussed before.
- Before we add the new scene we need to add a new navigation controller. A navigation controller allows to change the scene.
- Before we can tackle that problem have a look at your storyboard and your view and you can see a arrow before your view as you can also see from this screenshot. This arrow always points to only one controller and denotes which controller is the starting view for the app. We can change the initial point for the app. You can change the initial view my moving the arrow to another view or using attributes inspector. For now we don’t need to change it.
- Click on your view controller window in storyboard and go to Editor menu, click on Embed In item and select navigation controller.
- You should see a new controller that will appear before your main controller. Move the navigation controller to align it with the controller you have been working. See screenshot for an example. We are only doing this so all our views fit in our screen and we can manage the views easily.
- You can read about Navigation Controller from Xcode documentation. Go to help menu and Documentation and API Reference and type in UINavigationController in search and select the first option and read more about navigation controller.
- Now we can add a new scene. Show Utility Editor
- Drag a new view controller from the screen in the bottom section where we dragged buttons and labels onto the storyboard. Align the new controller in front of our old controller.
- Select the stop button first. Now press and hold control button and drag from the stop button to the new scene added. When you drop on the new scene you will see a popup. From the action segue section in the popup select show. A new connection from your old connection to the new controller should appear as you can see in this screenshot.
- Now run the app and click on the record button and then click the stop button. Now when you click the stop button a new scene will appear. Note on the top you will see a back button. You can click on the back button the return to the recording screen. The back button and the top bar is part of the navigation controller we added.
- Now go to the storyboard and for the recording screen in the top menu bar just below the battery icon double click in the middle of the menu bar and enter the text Record as you can see from this screenshot. This menu bar is part of the navigation controller and you can customize the title for each view separately
- Now run the app and the main recording screen will have the title Record. When you go to the next screen now instead of showing the text back on the top left button it will show the title of the main screen Record.
All the elements such as UIButton, UILabel and now UINavigationController is part of a view hierarchy set of classes named UIKit. UI in each refers to user interface. UIKit contains a lot of classes for different view and window management. Find all the classes for UIKit here. You will find UIButton, UILabel, and UINavigationController in one of subclasses on this page. As you can see UINavigationController is a specialized subclass of UIViewController(the class we have been inheriting in our viewcontroller.swift class) and contains code to manage navigating from one page to another.
Great we have just added a new scene. In the next tutorial we will build upon the new scene by adding buttons to play the audio and change the speed of the audio.
Part 5 of the series can be found here