Gain in-depth knowledge on how to create an iOS app using MVC design patterns and setting up a model. Learn to build a real-world app by storing data in the cloud and delivering it via REST API, a method widely adopted by many modern mobile applications.
Key Insights
- The tutorial discusses the use of MVC (Model, View, Controller) design pattern in developing iOS applications. MVC is widely used in mobile and web applications and separates the Data layer from the Controller layer for a more professional setup.
- The application discussed in the tutorial stored its data in the cloud, delivering it to the application via a REST API. This method allows data to be returned via web calls to specific URLs which are then interpreted by the app.
- The process of setting up a model to update the application involves creating a new class, adding a method to fetch the model’s data, and setting up the bandDetails array from the BandsTableViewController in the BandsModel class.
- The BandsTableViewController class is modified to work with the new model. This involves deleting old properties, creating an instance of the band model, and calling the model’s fetch method when the screen loads.
- The numberOfRowsInSection method in the BandsTableViewController.swift file is changed to return the count from the bandDetails array in the model. The cellForRowAt method is edited to configure the cell based on the model’s data.
- The prepare method is updated to pass data from the model. This change allows the application to function fully with data supported by the model.
Discover the essentials of iOS development with this detailed tutorial, including creating MVC design patterns, setting up a model, and transitioning from static to cloud-based data.
This exercise is excerpted from Noble Desktop’s past app development training materials and is compatible with iOS updates through 2021. To learn current skills in web development, check out our coding bootcamps in NYC and live online.
Topics Covered in This IOS Development Tutorial:
MVC Design Patterns, Setting up a Model
Exercise Overview
Up to this point, we have been constructing our app with static data. We did this so we could more easily learn the basics of working on an iOS application without having to stop and spend a lot of time talking about data. It’s served us well for now, however in the real-world it’s very unlikely that an app like this would have hard-coded data in it. If it did, we’d have to go in and manually update the arrays that store the bands’ data and re-submit to Apple each time we wanted to add or modify the details of a band. The more realistic scenario is that all of the bands’ data would be stored in the “Cloud” somewhere and get delivered to the application via a REST API. The term REST API means that data would be returned via web calls to certain URLs that would then be parsed/interpreted by the app. This is the way the majority of the applications you are used to using on your mobile devices work.
Getting Started
-
If you completed the previous exercise you can skip the following sidebar. We recommend you finish the previous exercises (1B–3C) before starting this one.
If you completed the previous exercise, Jive Factory.xcodeproj should still be open. If you closed it, re-open it (from yourname-iOS Dev Level 2 Class > Jive Factory).
If You Did Not Complete the Previous Exercises (1B–3C)
- Close any files you may have open and switch to the Desktop.
- Navigate to Class Files > yourname-iOS Dev Level 2 Class.
- Duplicate the Jive Factory Ready for the Real World folder.
- Rename the folder to Jive Factory.
- Open Jive Factory > Jive Factory.xcodeproj.
MVC: Model, View, Controller
Another new term that we are going to delve into is a concept called MVC which stands for: Model, View, Controller. MVC is a software design pattern that is widely used in mobile and web applications and in fact, iOS is based on using it. It sounds complicated but it’s really not. It exists to make our lives easier as developers. Up until this point we have been dealing with View Controllers and their views consistently, so we’re two-thirds of the way there. What we haven’t done is separate our Data layer from our Controller layer. Right now our data is all mixed in, which is not very professional.
The MVC concept is simple: The Controller talks to the Model and gets the data needed. The Controller interprets the data and tells the View how to display it to the user. In this way, the design, the application logic, and the data model are all kept in their own neat little places and if any of the three need to be changed, it can be done without breaking the rest of the application. It also makes it easier to work on an app with more than 12 developers, but we’ll deal with that later.
Setting up a Model
The first step in updating our application for the real-world is setting up a model and moving our data into it.
- In the Project navigator, select AppDelegate.swift. (We want the file to be added after this file, that’s why we had you select it.)
- Go to File > New > File or hit Cmd–N.
- Under iOS and Source, double–click on the Cocoa Touch Class template.
- For Class type: BandsModel
- From the Subclass of menu, choose NSObject (or start typing it and let Xcode autocomplete it for you).
- Make sure Language is set to Swift.
- Click Next.
- Make sure you are in the Jive Factory folder, and click Create.
- In the Project navigator, notice BandsModel.swift has been added. Now we have a class we can work with.
- The first thing we want to do is to put the bandDetails array into the BandsModel. Open the BandsModel.swift class, if it isn’t already.
-
Add the following bold code into the BandsModel class:
class BandsModel: NSObject { var bandDetails = [BandDetail]() }
-
Just below the bandDetails property, add a new method to fetch the model’s data:
class BandsModel: NSObject { var bandDetails = [BandDetail]() func fetch() { } }
- Now we are going to take the code that sets up the bandDetails array from the BandsTableViewController and paste it in the BandsModel class. Go to BandsTableViewController.swift.
- Select the code in the viewDidLoad method.
- Cut (Cmd–X) the code.
- Go back to BandsModel.swift.
-
Paste (Cmd–V) it all in the fetch method. Your code should look as follows:
func fetch() { let nicoleAtkinsBandDetail = BandDetail() nicoleAtkinsBandDetail.bandName = "Nicole Atkins" nicoleAtkinsBandDetail.bandType = "Rock" nicoleAtkinsBandDetail.bandDescription = "Nicole will knock your socks off." nicoleAtkinsBandDetail.fullImageName = "full-nicole-atkins"
Code Omitted To Save Space
bandDetails.append(nicoleAtkinsBandDetail) bandDetails.append(ambulanceLtdDetails) bandDetails.append(sleepiesDetails) bandDetails.append(blackAngelsDetails) }
Hit Cmd–S.
- Now let’s finish fixing up our BandsTableViewController class so that it can work with our model. Go to BandsTableViewController.swift.
-
Find the four properties at the top of the file and delete them:
let bandTitles = ["Nicole Atkins", "Ambulance LTD", "Sleepies", "Black Angels"] let bandSubTitles = ["Tue 5/1", "Fri 5/4", "Sat 5/5", "Sun 5/6", ] let bandImageNames = ["thumb-nicole-atkins", "thumb-ambulance-ltd", "thumb-sleepies", "thumb-black-angels"] var bandDetails = [BandDetail]()
-
Now we need to create an instance of the band model where the old properties once existed. Add the following bold code:
class BandsTableViewController: UITableViewController { let bandsModel = BandsModel() override func viewDidLoad() {
-
Now in the viewDidLoad method we want to call the model’s fetch method. What’s going to happen here is that when this screen gets loaded, it will trigger the model to parse the data so we can use it to build the table and display it to the user. Add the following bold code (around line 18):
override func viewDidLoad() { super.viewDidLoad() bandsModel.fetch() }
We need to fix up our table a bit. You’ll remember from previous exercises that we’re using the data from the arrays to populate the table while passing the data stored in the bandDetail object to the details page. This actually isn’t a great method. A better way is to have a single data source that is shared by the whole app.
-
Still in BandsTableViewController.swift, locate the numberOfRowsInSection method. Replace everything inside it with the bold code, changing its return to the count from the bandDetails array in the model:
override func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int { return bandsModel.bandDetails.count }
-
In the cellForRowAt method, we will configure the cell based on the model’s data. Add the bold code as shown below:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "bandCell", for: indexPath) // Configure the cell… let bandDetail = bandsModel.bandDetails[indexPath.row] cell.textLabel?.text = bandTitles[indexPath.row] cell.detailTextLabel?.text = bandSubTitles[indexPath.row] cell.imageView?.image = UIImage(named: bandImageNames[indexPath.row]) return cell }
NOTE: Notice that the first thing we do is create an instance of the bandDetail object from the information in the array. This allows us to neatly capture and grab the data for later use.
-
Just below that, edit the following three lines as shown:
override func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell { let cell = tableView.dequeueReusableCell(withIdentifier: "bandCell", for: indexPath) // Configure the cell… let bandDetail = bandsModel.bandDetails[indexPath.row] cell.textLabel?.text = bandDetail.bandName cell.detailTextLabel?.text = bandDetail.nextShowDate cell.imageView?.image = UIImage(named: bandDetail.thumbImageName!) return cell }
-
Finally we need to go to the prepare method and update it to pass data from the model. Scroll to the bottom of the file to add the bold code shown below:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if (segue.identifier == "showDetail") { if let indexPath = self.tableView.indexPathForSelectedRow { let bandsDetailViewController:BandsDetailViewController = segue.destinationViewController as! BandsDetailViewController let bandDetail = bandsModel.bandDetails[indexPath.row] bandsDetailViewController.currentBandDetail = bandDetails[indexPath.row]
-
Edit the code as shown:
override func prepare(for segue: UIStoryboardSegue, sender: Any?) { if (segue.identifier == "showDetail") { if let indexPath = self.tableView.indexPathForSelectedRow { let bandsDetailViewController:BandsDetailViewController = segue.destinationViewController as! BandsDetailViewController let bandDetail = bandsModel.bandDetails[indexPath.row] bandsDetailViewController.currentBandDetail = bandDetail
- Click the Run button.
- Go ahead and explore the app’s features to see the app is functioning fully, but now its data is being supported by the model.
- Return to Xcode.
Leave the file open so we can continue with it in the next exercise.