In order to service our views with dynamic content, we need to create a data source that will feed our interface. We’ll define a data model which describes our content and incorporate it into the structure of our UI needs.
Finally, time to start coding!
Oh wait, we haven't created a project yet... 😉
Starter project
Looking at our design decisions, we can conclude that we'll need to implement the following elements:
Navigation controller
Main view controller presenting the list of items
Another view controller displaying more details for a selected item
Complete the following sequence:
Create a single view project in Xcode.
On the Main storyboard, embed the default view controller in a navigation controller.
Rename the default Swift file associated with the default view controller to:
MediaListViewController.swift
.Add another view controller to the storyboard and create a Swift file:
MediaDetailViewController.swift
.Make sure both files have respective initial code:
Main view controller:
import UIKitclass MediaListViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view, typically from a nib.}}
Detail view controller:
import UIKitclass MediaDetailViewController: UIViewController {override func viewDidLoad() {super.viewDidLoad()// Do any additional setup after loading the view, typically from a nib.}}
Make sure both View controllers on the storyboard are associated with the two files we just discussed above.
You may go the extra mile and source some cool items to make up an app icon and a launch screen!
Back to setting up the project - in Deployment info, set the Devices property to iPhone and Orientations to Portrait and uncheck the rest.
And of course, following the MVC architecture, organize the files in respective groups, placing the rest of the files into the Supporting files group.
As a shortcut, download my starter project with all of the above already done! 😇 Feel free to modify of course!
Data model
Now we are ready to create a data model. Looking closer at our requirements, we'll need to describe the following elements with respective characteristics:
A media item described as:
Artwork
Song name
Artist name
Collection it is a part of
iTunes for more details
A swag item, such as:
Title
Artwork
External URL for more details
Let's take a sneak-peek at the external resource we are going to use: iTunes Search API. There we can see what media attributes we can get and what they are named.
Property needed | iTunes label |
Artwork | artworkUrl100 |
Name of the song | trackName |
Artist name | artistName |
Collection | collectionName |
iTunes link | trackViewUrl |
We could use the same names, but it's not mandatory. And I recommend not to, for two reasons:
Your views are likely to be more abstract and you may want to change things up as you develop your app. For example, display
collectionCensoredName
instead of the originally chosencollectionName
.You need to switch your source - use an API different from iTunes, or incorporate multiple APIs within your app - but you will need to unify the information you'll be presenting to the user so that the user doesn't even have to know where each piece of information comes from.
Matching external attributes to the corresponding local variables and properties is called mapping. Typically, it's done on a per-object basis, stating which field corresponds to which property.
Considering the above, we are going to create the core of our data model based on our app needs, taking into consideration the iTunes structure.
For our Media object, we are going to create two classes. The first one will store a few elements that are necessary to present media items on the list view. And the second one will inherit from the first one, and will expand the number of attributes it will store to be presented on the detailed view:
MediaBrief
- to hold the info for the listMedia
- subclass of the MediaBrief - to hold all the info
And the third data object we'll need is Swag
.
We can now translate the information above into classes and store in respective files:
Media.swift:
import Foundation
class MediaBrief {
var id: Int
var title: String
var artistName: String
var artworkUrl: String
var artworkData: Data?
init(id: Int, title: String, artistName: String, artworkUrl: String) {
self.id = id
self.title = title
self.artistName = artistName
self.artworkUrl = artworkUrl
}
}
class Media: MediaBrief {
var collection: String?
var sourceUrl: String
init(id: Int, title: String, artistName: String, artworkUrl: String, sourceUrl: String) {
self.sourceUrl = sourceUrl
super.init(id: id, title: title, artistName: artistName, artworkUrl: artworkUrl)
}
}
Swag.swift:
import Foundation
class Swag {
var id: Int
var title: String
var artworkUrl: String
var sourceUrl: String
var artworkData: Data?
init(id: Int, title: String, artworkUrl: String, sourceUrl: String) {
self.id = id
self.title = title
self.artworkUrl = artworkUrl
self.sourceUrl = sourceUrl
}
}
Looking at the code, we may notice two elements we previously didn't discuss:
id
- most of the data entities have unique identifiers that allow smooth identification of an object. It's mostly used internally even if not directly by the user. In the case of iTunes API, this value is used to retrieve lookup information (using lookup API endpoint).artworkData
- while receiving the data for search or lookup (search and lookup API endpoints), we are getting a reference to an image, not the image data itself. We could use this reference to fetch the actual image data every time we need to display an image; however, to save time and resources, we could also cache the image data and use it in subsequent circumstances.
Another important aspect to notice is that most of the properties are non-optional. We want to reinforce that this information is delivered from the server and will not display an item without it. This leads us to create respective initializers that reinforce this decision.
Well done! We are now ready to store the data in property-structured variables! 😎
Let's recap!
Following the MVP, start organizing your code from the beginning so that the MVC is easily recognizable.
Describe your data model based on internal requirements and local implementation, while taking the external description into consideration.
Matching property names within the app and API field names is called mapping.