Developing iOS apps with MVC: A practical example

Last week, I explored what the design pattern “Model-View-Controller” (MVC) is and created a playground to demonstrate the idea. But what does this look like a full-fledged application with API calls and Storyboards and design requirements? This week, we’ll see how that plays out.

Design

Imagine you’ve got a new project to do, and design have given you what to implement. It’s a news app which hooks up to NewsAPI, which generously allows you to request news sources and articles for free. Here’s what your designer hands off to you:

The application is very simple, but it does everything you need a news reader to do:

  1. We have a launch screen
  2. A list a square icons for each news source
  3. A table of news articles, with images, the author, and the title
  4. A web view with the full article

Planning

How does this design decompose into MVC components?

View Controller

Let’s start with view controllers, as view controllers are almost 1:1 with a designer’s screens. In this case, the launch screen will be done simply in our LaunchScreen.storyboard file, we’ll have a SourcesViewController, an ArticlesViewController, and then we’ll reach for the pre-built SFSafariViewController for the last view.

View

What views will each of these view controllers have? The launch screen will only need a UILabel, there isn’t much to do there. The SourcesViewControllerprobably needs a UICollectionView, with a custom SourceCollectionViewCell that we’ll make. The ArticlesViewController would be best as a UITableView, along with a custom ArticleTableViewCell.

Model

To determine what our model layer looks like, we cannot go from the designs, as it’s not a visual component, but rather, we must check the API documentation from NewsAPI.

Let’s start with the documentation for the response from the source’s API call:

status (string) – If the request was successful or not. Options: ok, error. In the case of error a code and message property will be populated.
sources (array) – A list of the news sources and blogs available on News API.

id (string) – The unique identifier for the news source. This is needed when querying the /articles endpoint to retrieve article metadata.
name (string) – The display-friendly name of the news source.
description (string) – A brief description of the news source and what area they specialize in.
url (string) – The base URL or homepage of the source.
category (string) – The topic category that the source focuses on.
Possible options: business, entertainment, gaming, general, music, politics, science-and-nature, sport, technology
language (string) – The 2-letter ISO-639-1 code for the language that the source is written in.
Possible options: en, de, fr
country (string) – The 2-letter ISO 3166-1 code of the country that the source mainly focuses on.
Available options: au, de, gb, in, it, us
sortBysAvailable (array) – The available headline lists for the news source. The possible options are top, latest and popular.

top Indicates this source can return a list of headlines sorted in the order they appear on the source’ homepage.
latest Indicates this source can return a list of headlines sorted in chronological order, newest first.
popular Indicates this source can return a list of its current most popular headlines.

There’s no one right way to do this, but roughly, our models are going to follow the structure and variables of our API. What I read here is that we’re going to need a SourcesResponse model with the status variable and the sources as an array of Source models. A Source model has an ID, a name, a description, a URL, a category (probably best to make this an enum, as it has a closed set of possible values), a language, and a country (again both these last ones are best as enums).

Let’s check out the documentation on the articles response:

status (string) – If the request was successful or not. Options: ok, error. In the case of error a code and message property will be populated.
source (string) – The identifier of the source requested.
sortBy (string) – Which type of article list is being returned. Options: top, latest, popular.
articles (array) The list of headline metadata requested.

author (string) – The author of the article.
description (string) – A description or preface for the article.
title (string) – The headline or title of the article.
url (string) – The direct URL to the content page of the article.
urlToImage (string) – The URL to a relevant image for the article.
publishedAt (string) – The best attempt at finding a date for the article, in UTC (+0).

Again, there’s no one right or settled way to turn JSON into model objects, but what I see here is that we’re going to need a ArticlesResponse model with an array of Article objects, which each have an author, description, title, url, urlToImage, and published at, all as Strings.

So in all, if we give a Swift struct to each entity and a Swift enum to each closed set of values, we’ll end up with these models:

  • Article
  • ArticlesResponse
  • Source
  • SourcesResponse
  • Category
  • Country
  • Language
  • Sort

Visualisation

How does this look like in the graphs we made last week? Let’s take the ArticlesViewController as an example:

But of course, this single MVC group is going to have to work with all the others in the full implementation. That looks something like this:

But this is beginning to get messy, so let’s separate all of our files into their respective layers:

Development

Now that we have a plan, it’s time to set it in motion. Fortunately, not only are we working with a designer, but an iOS architect that has created a shell of project for us using the information above, but it’s going to be up to us to add the implementation. You can download that shell here. You’ll note that it includes an API client pre-built for us, and the creation of an API client is outside the purview of our MVC discussion but it’s a very worthwhile topic I’ll devote time to in a latter post.

View

First, you should build your Storyboard to spec. First, add the label to the LaunchScreen.storyboard file. You’ll need one UINavigationController and two UIViewControllers, one with a UICollectionView and one with a UITableView. The collection view and table view will need a custom cell each, with an image view and labels each. Refer to the design to get this just right.

Now that we have these built in Storyboard, we’ll need to create corresponding source files for each cell type. Here’s what that SourceCollectionViewCell should look like:

class SourceCollectionViewCell: UICollectionViewCell, ReuseIdentifiable {
    static var ReuseIdentifier : String { return "SourceCollectionViewCell" }

    @IBOutlet weak var iconImageView: UIImageView!
    @IBOutlet weak var nameLabel: UILabel!

    override func awakeFromNib() {
        super.awakeFromNib()
        prepareForReuse()
    }

    override func prepareForReuse() {
        super.prepareForReuse()
        iconImageView.image = nil
        nameLabel.text = ""
    }
}

You should use this as an example to build ArticleTableViewCell, which is much the same in form. You should also use this opportunity to connect the table view and collection view as IBOutlets to their respective UIViewController and set their delegates and data sources to, also, their respective view controller.

Model

Now that we have the easy stuff out the way, let’s build our first model. The article is a good place to start, I suspect it looks something like this:

struct Article {
 let author: String?
 let description: String?
 let title: String?
 let url: String?
 let urlToImage: String?
 let publishedAt: String?
}

We’re choosing a struct because it is a lighter entity in the Swift language than a class, but really there are reasons to go either way. These models do not exist in a vacuum however, we need to transform these models from JSON into structs. Fortunately, our architect has given a convenient means of doing so with the JSONTransformable protocol, which is very simple:

protocol JSONTransformable {
 init(json: Any)
}

When our model structs conform to this, we’ll add the implementation for converting them from JSON represented as an “Any”, which could be an array or dictionary depending on our API responses. What does our struct look like with this implementation?

struct Article: JSONTransformable {
    let author: String?
    let description: String?
    let title: String?
    let url: String?
    let urlToImage: String?
    let publishedAt: String?

    init(json: Any) {
        let jsonDictionary = json as? [String : Any]
        author = jsonDictionary?["author"] as? String
        description = jsonDictionary?["description"] as? String
        title = jsonDictionary?["title"] as? String
        url = jsonDictionary?["url"] as? String
        urlToImage = jsonDictionary?["urlToImage"] as? String
        publishedAt = jsonDictionary?["publishedAt"] as? String
    }
}

And with a little magic from Swift generics in our API client, these can now be converted from their JSON representations returned from the API. Let’s give the Articles response model the same treatment:

struct ArticlesResponse: JSONTransformable {
    let status: String?
    let articles: [Article]?

    init(json: Any) {
        let jsonDictionary = json as? [String : Any]
        status = jsonDictionary?["status"] as? String
        if let articlesJSONArray = jsonDictionary?["articles"] as? [[String: Any]] {
            var anArticles: [Article] = []
            for sourceJSONDictionary in articlesJSONArray {
                anArticles.append(Article(json: sourceJSONDictionary))
            }
            articles = anArticles
        } else {
            articles = nil
        }
    }
}

Notice how this initializer uses the JSON-based initializer from our Article class, meaning that when we request this response from our API, this initializer will cascade through all the article JSON entries to build structs for each. We’ll need to do the same for both the Source and SourcesResponse models, which is left as an exercise to the reader! (You’ll also find it as a download at the end.

But the Article and Source models aren’t the only types of models we have, there are also the enum models for the Language and Country, etc. Let’s see how one of those looks:

enum Category: String {
    case business = "business"
    case entertainment = "entertainment"
    case gaming = "gaming"
    case general = "general"
    case music = "music"
    case politics = "politics"
    case science = "science-and-nature"
    case sport = "sport"
    case technology = "technology"
}

This has the typed name on the left and the value on the right side of the equals sign, making it easy to parse these using the raw value initializer of these objects. You’ll see this in the initializer for Source. You should use this as an example to create the models for Country, Language, and Sort.

View Controller

Now that we have our models finished and our views finished, it’s time to write the glue code between our two layers: the view controllers. First, let’s get our Source view controller working:

class SourcesViewController: UIViewController {

    let api = NewsAPI()
    var sources: [Source] = []

    @IBOutlet weak var collectionView: UICollectionView!
    @IBOutlet weak var collectionViewFlowLayout: UICollectionViewFlowLayout!

    override func viewDidLoad() {
        super.viewDidLoad()

        api.load(.sources(categories: nil, languages: nil, countries: nil)) { [weak self] (response: SourcesResponse?, error:Error?) in
            self?.sources = response?.sources ?? []
            self?.collectionView.reloadData()
        }
    }
}

extension SourcesViewController: UICollectionViewDataSource {
    func collectionView(_ collectionView: UICollectionView, numberOfItemsInSection section: Int) -> Int {
        return sources.count
    }

    func collectionView(_ collectionView: UICollectionView, cellForItemAt indexPath: IndexPath) -> UICollectionViewCell {
        let cell : SourceCollectionViewCell = collectionView.dequeueReusableCell(for: indexPath)
        cell.iconImageView.setIconImage(from: sources[indexPath.row].url)
        cell.nameLabel.text = sources[indexPath.row].name
        return cell
    }
}

extension SourcesViewController: UICollectionViewDelegateFlowLayout {
    func collectionView(_ collectionView: UICollectionView, layout collectionViewLayout: UICollectionViewLayout, sizeForItemAt indexPath: IndexPath) -> CGSize {
        let numberOfCellsPerLineFloat: CGFloat = 2
        let itemWidthWithoutConsideringInteritemSpace = collectionViewFlowLayout.collectionViewWidthWithoutInsets / numberOfCellsPerLineFloat
        let numberOfInteritemSpaces = (numberOfCellsPerLineFloat - 1)
        let amountOfInteritemSpacePerCell = (collectionViewFlowLayout.minimumInteritemSpacing / numberOfCellsPerLineFloat)
        let itemWidth = itemWidthWithoutConsideringInteritemSpace - (numberOfInteritemSpaces * amountOfInteritemSpacePerCell)
        return CGSize(width: itemWidth, height: 208)
    }
}

Notice how the view controller has access to both the model and view, but neither the model nor the view has access to each other. This property results in one of the big benefits of MVC, in that if either your model or view changes, as I assure you they will, you minimize the amount of code you will need to re-write because your models and views are completely independent, and in fact, could be re-used in other parts of your applications or even other applications.

But this isn’t quite the whole picture, let’s get our ArticlesViewController working:

class ArticlesViewController: UIViewController {
    let api = NewsAPI()
    var source: Source!
    var articles: [Article] = []
    
    @IBOutlet weak var tableView: UITableView!

    override func viewDidLoad() {
        title = source.name

        api.load(.articles(source: source, sort: nil)) { [weak self] (response:ArticlesResponse?, error:Error?) in
            self?.articles = response?.articles ?? []
            self?.tableView.reloadData()
        }
    }
}

extension ArticlesViewController: UITableViewDataSource {
    func tableView(_ tableView: UITableView, numberOfRowsInSection section: Int) -> Int {
        return articles.count
    }

    func tableView(_ tableView: UITableView, cellForRowAt indexPath: IndexPath) -> UITableViewCell {
        let cell: ArticleTableViewCell = tableView.dequeueReusableCell(for: indexPath)
        cell.authorLabel.text = articles[indexPath.row].author
        cell.previewImageView.setImage(from: articles[indexPath.row].urlToImage)
        cell.theTitleLabel.text = articles[indexPath.row].title
        return cell
    }
}

If you try to transition between the two view controllers by selecting a source, you will notice a crash. That’s because we need to pass the selected source from the Source view controller to the Articles view controller in it’s prepareForSegue implementation (Be sure to add an identifier in your Storyboard, I also chose to represent my Segues as an enum).

class SourcesViewController: UIViewController {
    /* omitted to save space */
    override func prepare(for segue: UIStoryboardSegue, sender: Any?) {
        switch segue.identifier ?? "" {
        case Segue.sourcesToArticles.rawValue:
            let selectedIndexPath = collectionView.indexPathsForSelectedItems?.first ?? IndexPath(item: 0, section: 0)
            let destination = segue.destination as! ArticlesViewController
            destination.source = sources[selectedIndexPath.row]
        default:
            ()
        }
    }
}

This should result in a successful transition from one view controller to the next, but when you select an article from the table view of the Articles view controller, unfortunately we run into another crash. This is because we need to add the implementation of UITableViewDelegate’s didSelectItemAtIndexPath to our Articles view controller. So let’s take a look:

extension ArticlesViewController: UITableViewDelegate {
    func tableView(_ tableView: UITableView, didSelectRowAt indexPath: IndexPath) {
        let article = articles[indexPath.row]
        if let url = URL(string: article.url ?? "") {
            let svc = SFSafariViewController(url: url)
            present(svc, animated: true, completion: nil)
        }
    }
}

Now, if we run it, it should push a web view controller when we do select an article.

Final Product

Here’s a video of what this app will look like with everything finished!

It looks great! I’m sure our designer will be proud!

Conclusion

We’ve seen how you can take a design and decompose it into views and view controllers, take an API spec and decompose it into model entities, and use that plan to implement an iOS app in Swift. To see some of the benefits this approach has and the arguments for it, I recommend checking out my last post on this topic. You should also know that this approach isn’t the only right way to develop in Swift for iOS or even nearly perfect. But it is the official design pattern for iOS and for good reason: it’s a reasonable place to start. In a forthcoming post, we’ll explore adding view models to this example. I’ll also write a post about the considerations in designing an API client. If you have any questions, feel free to add a comment below, reach out to me, or if you happen to be reading this before September 20th, 2017, come check this out live at the Noble iOS Meetup. Here’s the full file for those that want to check out the full working version.

What is Model-View-Controller (MVC) and why does iOS use it?

Last week I explored some implementation details of MMVM on iOS, but I realized that for people just beginning with iOS, this post was going to be of no help because it assumes knowledge of the more basic Model-View-Controller (MVC) design pattern. To rectify that, today we’ll explore MVC. This post is meant for someone that is new to iOS, perhaps they’re in a bootcamp or a class or teaching themselves; this will only be useful to very junior developers, but let’s roll.

Some theory and graphs

MVC is a way of organizing your code that allows you to divvy up the work of writing a feature of an application into three independent parts: the model, the view, and the controller. The model is your representation of your app’s subject – for instance, if you’re making a social networking app, a natural “model” class would be the “User” class, where username, bio, and profile picture are stored. The view, on the other hand, is what the user actually sees, and it will more likely than not manifest itself as a “UIView” class, such as UITextView or UIImageView, which you might have in a “UserProfileView” for your social network, for example. The controller is what sits in between these two layers of code, requesting from the model the information to pass to the view for presentation to the user. Here’s a graph of what this relationship looks like:

This graphs makes it clear how the user actions flow through your layers and how this results in an update to what the user sees. The “view” picks up the user’s interaction and sends the message of being tapped or swiped to the controller, which uses this message to tell the model layer to update itself, which in turn sends a message back to the controller of success or failure to update, which cascade into the view, finally getting presented to the user there.

Your application isn’t limited to just one of these objects, quite the contrary, an application is going to have many MVC groups working together to create the final product:

As a project grows like this, you’ll eventually find that you stop thinking about features in terms of 3 unique MVC items each, but more as “layers”. The reason for this is that for big projects, a controller will end up with a multitude of views and models each, where a checkout view controller, for example, might also use a user model and product model to populate its checkout view and the subviews.

More practically, some code

Let’s write some code that illustrates just the bare bones principles outlined above: that we should strictly separate our views from our models, and use a controller to glue the two together. Our example app is going to be a tap counter that has a User for sake of staying true to some of the images above.

Model

The easy part should come first, here’s what a model looks like:

struct UserModel {
 var username: String
 var tapCount: Int
}

This struct models our “problem”: we want to display a username and the number of times that user has tapped our app, and so that’s all our struct represents. There is no mention of UIViews of UIViewControllers, this model is completely independent of that. In fact, all you need to be able to utilize this model is the Swift language, wherever it might be running, on a Mac, iPhone, iPad, and perhaps on day on the server too, but that’s a topic for another day.

View

Now let’s create a view. Our view is going to need a button to receive the tap, and a label to display the username and the tap count. On iOS and with Swift, that looks like this:

class ProfileView: UIView {
 let button = UIButton()
 let label = UILabel()
}

Because we’re doing this in a playground, we’re going to need to configure our UIView programmatically. This isn’t so relevant to modern iOS, but it also isn’t very difficult. In our ProfileView, we’re going to implement a custom initializer like this:

    override init(frame: CGRect) {
        super.init(frame: frame)
        backgroundColor = .blue
        button.setTitleColor(UIColor.white, for: .normal)
        button.setTitleColor(UIColor.gray, for: .highlighted)
        button.addTarget(self, action: #selector(didTapButton(sender:)), for: .touchUpInside)
        button.backgroundColor = .black
        button.layer.borderWidth = 1
        button.layer.borderColor = UIColor.white.cgColor
        button.layer.cornerRadius = 5
        label.textColor = .white
        let stackView = UIStackView(arrangedSubviews: [button, label])
        stackView.axis = .vertical
        stackView.alignment = .center
        stackView.spacing = 20
        addSubview(stackView)
        stackView.bindFrameToSuperviewBounds() /* see implementation later in this exercise */
    }

Because we want a strict separation between the model layer and the view layer, we’re not going to add a variable for the user in our view, as that could lead to non-canonical user instances floating about, that is, versions of the user that aren’t controlled by their rightful controller, we’re going to add a function that configures our view for a user, like so:

    func configure(with user: UserModel) {
        button.setTitle("Tap here", for: .normal)
        label.text = "\(user.username) Tap Count: \(user.tapCount)"
    }

Going back to our graphs from earlier, we see that the UIView is meant to handle user interaction, and in our initializer we declared that our button was to tell this view when it is touched-up-inside, so we’re going to need to implement that function. Before we do that, to keep our separation between Controller and View layers, we’re also going to need a delegate using a Swift protocol to sit between the two layers. That’ll look like this:

protocol ProfileViewDelegate: NSObjectProtocol {
    func profileViewDidTapButton()
}

class ProfileView: UIView {
    /* ommitted to save space */
    
    weak var delegate: ProfileViewDelegate?
    
    /* ommitted to save space */
    
    func didTapButton(sender: UIButton) {
        delegate?.profileViewDidTapButton()
    }
}

Controller

Now that both our view and model are completely set up, it’s time to write some code that glues these two layers together. We’re going to create a UIViewController and give it a view and a model as properties:

class ProfileViewController: UIViewController {
    let profileView = ProfileView(frame: CGRect(x: 0, y: 0, width: 200, height: 100))
    var userModel = UserModel(username: "PLJNS", tapCount: 0)
}

We’re now going to need to configure our view with our model and position it, let’s do that in viewDidLoad:

    override func viewDidLoad() {
        super.viewDidLoad()

        profileView.configure(with: userModel)
        profileView.center = view.center
        profileView.delegate = self

        view.addSubview(profileView)
    }

We now should find that this is all well and good, except that we need our view controller to conform to our view’s delegate’s protocol so that they can communicate when the user taps, let’s add it in an extension:

extension ProfileViewController: ProfileViewDelegate {
    func profileViewDidTapButton() {
        userModel.tapCount += 1
        profileView.configure(with: userModel)
    }
}

Okay, but why?

The benefits of adopting this style of divvying up the work are that it allows you to sometimes reuse code, it decouples view logic from model (or “business”) logic making your code more amenable to change, and it can reduce the amount of bugs you have by helping not to introduce them. In our example, we could take our UserModel everywhere. We could have another view controller conform to our view’s protocol. We could change the UILabel to a UITextView. We can do this because all of the parts are independent from one another.

This isn’t the only way to organize your project, and as you develop bigger projects you may find that this approach has downside too. For instance, our model and view layer aren’t really that separated in that the know about one another’s existence, so if you move from a UserModel to something else you’d have to update that code. One solution to this problem is know as MVVM, which I cover here. You might also find that because a “controller” is just whatever isn’t a view or model, it ends up being an awful lot indeed, perhaps 10s of thousands of lines if you’re not careful. This is playfully known as massive view controller, and it can be a serious hindrance to your application. One design patterns to solving this problem is known as VIPER, which I’ll cover in a future post.

You can find this code in this post in Playground form here.

Pokemon Go, Nintendo’s market value, and intellectual property

Like seemingly everyone near my age and many people below and above it, I’ve been playing Pokemon Go. It’s fun, and the nostalgia is palpable. It isn’t particularly well-done, however, the most innovative products perhaps necessarily rushed, and so, my criticisms:

  • I hate having to give access to my full Google account to some shady subdivision without the public oversight and reputation of Google proper;
  • It makes me sad to throw out Pokemon I trained since the beginning or caught in meaningful locations for much more powerful and otherwise identical Pokemon I find on my commute;
  • It destroys battery (but to be fair, the GameBoy was pretty awful at that too).

The news of Pokemon Go made it to Wall Street, and Pavel Alpeyev and Yuji Nakamura (via John Gruber) report for Bloomberg that they like what they see:

The company has added more than $7 billion in market value since last week’s debut of a new smartphone app for its Pokemon fantasy monster character franchise. The game, which lets users track down virtual monsters in their vicinity, has topped the free-to-download app charts for Apple in the U.S. and Australia since its release on July 7, according to market researcher App Annie.

Nintendo’s shares responded with their biggest intraday jump since at least 1983, when the stock started trading in Tokyo, climbing as much as 25 percent on Monday. Investors are taking Pokemon’s early success as a sign of things to come for a company that has yet to commit the most popular characters from its Mario or Zelda franchises to mobile gaming apps.

The lesson I see here is not necessarily that this is a tipping point for AR/VR but rather that it’s still exceedingly good business to be in intellectual property. Consider that Niantec released an AR app before this that was met with a whimper, but when some IP from 1999 is added, a whole generation loses their collective mind and goes outside. The success of Pokemon Go is a powerful reminder of why companies like Marvel, Games Workshop, and Nintendo defend their IP so fervently: it can add $7 billion to your market value even 10 years after its inception.

I also caught an Electabuzz I’m quite proud of, and have a viciously high-level Pinsir.

Custom fonts with Dynamic Type in Interface Builder

Managing custom font text styles in Interface Builder and in code has always been a pain point for me when developing for iOS. For instance, what’s the best place to define text styles? Is it in the Interface Builder document? This grants you a great WYSIWYG experience, allows you to quickly change and iterate, and maybe even lets non-developers modify appearance. Or should it be in code? This makes changes to the appearance more explicit and easier to merge, as well as being an easier target for large-scale refactoring when an app-wide design change inevitably happens. I thought there must be a better way, and here’s my proposal. If you aren’t one for rhetoric, here’s some working code.

In both of the above scenarios, the text style is static: it’s defined either in the nib file or in the source file, and barring some runtime changes, it is constant. On the contrary, if your app uses the default iOS font, which is the beautifully utilitarian San Fransisco font since iOS 9, your app can take advantage of a system-level feature known as Dynamic Type. Dynamic Type allows the user to set the base font size used by the operating system on a scale from extra small to extra large. Apps that use system text styles can scale their fonts’ sizes up or down to account for the user’s preferences. But not all of us live in an all-white room where beauty can meet form and function: sometimes an app needs a custom font to express its own personality. It would be a shame if this requirement came at the cost of adjusting type size to a user’s preference, and fortunately, I have some code which lets you have the best of all these worlds:

  1. Define text styles in Interface Builder to take advantage of the WYSIWYG editor and great user experience;
  2. Change custom fonts quickly and easily by modifying source code;
  3. Adjust your custom font to user text style preferences using Dynamic Type.

The way that I accomplished this is two-fold: first you need to define your custom font’s various text styles, and secondly you need to override your Label’s and Text View’s font with your own with a custom subclass which overrides the font descriptor for text style method, as we’ll see.

I found out how to define custom sizes and font styles from this Stack Overflow post. The Stack Overflow answer isn’t quite right for me, because I wanted an all-Swift solution with all text styles, but it lays out the methodology for an implementation which I’ve used. Here’s the definition for UIFontTextStyleBody:

extension UIFontDescriptor {
    class func preferredAvenirNextFontDescriptorWithTextStyle(style: String) -> UIFontDescriptor {
        var onceToken: dispatch_once_t = 0
        var fontSizeTable: [String: Dictionary] = Dictionary()
        dispatch_once(&onceToken, { fontSizeTable = [
            UIFontTextStyleBody: [
                UIContentSizeCategoryAccessibilityExtraExtraExtraLarge: 21,
                UIContentSizeCategoryAccessibilityExtraExtraLarge: 20,
                UIContentSizeCategoryAccessibilityExtraLarge: 19,
                UIContentSizeCategoryAccessibilityLarge: 19,
                UIContentSizeCategoryAccessibilityMedium: 18,
                UIContentSizeCategoryExtraExtraExtraLarge: 18,
                UIContentSizeCategoryExtraExtraLarge: 17,
                UIContentSizeCategoryExtraLarge: 16,
                UIContentSizeCategoryLarge: 15,
                UIContentSizeCategoryMedium: 14,
                UIContentSizeCategorySmall: 13,
                UIContentSizeCategoryExtraSmall: 12
            ], ...
        ]})
        let contentSize = UIApplication.sharedApplication().preferredContentSizeCategory
        let sizes = fontSizeTable[style]!
        let size = sizes[contentSize]!
        return UIFontDescriptor(name:self.preferredFontName(), size: CGFloat(size))
    }
}

This code will first key on your text style name, then key on your users content size, which will yield a font size that you or your designers define. Next, we’ll get an example nib going with some labels with all of the text styles we want to support. I added a label for each text style and placed them in a Stack View:

Screen Shot 2016-03-07 at 10.14.43 PM

Interface Builder is going to show the system font with Apple’s font sizes. While we cannot change this about Interface Builder, we can change how our labels will interpret their text styles at runtime, and we can do that with a short and sweet label subclass, which we’ll set all our labels to. This way of getting a Label’s font description comes from this Stack Overflow post. Check it out:

class CFDTLabel: UILabel {
    override func awakeFromNib() {
        super.awakeFromNib()
        if let textStyle = self.font.fontDescriptor().objectForKey(UIFontDescriptorTextStyleAttribute) as? String {
            let font = UIFont(descriptor: UIFontDescriptor.preferredAvenirNextFontDescriptorWithTextStyle(textStyle), size: 0)
            self.font = font
        }
    }
}

Now, each time we have a label and set its text style, it’ll ask out custom method for the text style we defined in our UIFont extension. And that’s it, when we run our app we see our beautiful custom font which adjusts wit Dynamic Type.

Simulator Screen Shot Mar 7, 2016, 10.30.42 PMThis approach will be well-suited to you if you need a solution which lets define text styles in Interface Builder, adjust text styles quickly across your whole application, and scales up or down to meet your user’s font preferences. This last point is an important feature for people with different eyesight than the average: I’ve seen people use smaller text to fit more on the screen and larger text to make it easier to see.

Android and iOS development side-by-side

Mobile platforms are polarizing, and it doesn’t help that’s there’s effectively only two. To that effect, I thought it’d be instructional to complete the same simple tutorial on both platforms to get an appreciation of what each does well and what each does differently. This tutorial will read something like “beginning Android for iOS developers.” The Android portion of this tutorial is inspired by “Android Programming: The Big Nerd Ranch Guide” by Bill Phillips, Christ Stewart, Brian Hardy, and Kristin Marsicano (if you want a more rigorous look at how to do this on Android rather than a compare and contrast, it’s a good book). The goal is to make an app which presents the user with a single question and informs them if it’s correct or incorrect.

Let’s start with Android. Some preliminaries: install Android Studio and the SDK installed on your computer and start a project. Now, navigate to your custom activity XML file (app/src/main/res/layout/activity_my.xml) and create a RelativeLayoutTextView, and two Button objects.

Note that the visual editor gives you the option to either input the text into the text views and buttons directly or create a new “value” for it, and either is fine. The new value option is quite interesting, however, as it works by placing the string in an XML file of your choosing and referencing it with a key-value pair. I imagine this is hugely useful when reviewing copy or localizing, but it does add a level of indirection for smaller projects where it’s not needed. String management is a pain-point I experience on iOS, so I definitely appreciate this feature.

You should also be sure to look at the properties of your button objects and give them IDs. The IDs are used to generate a file called R.java that maps this IDs to constants so you can access them at runtime. This is the same file that the strings get entered in to. I find this cumbersome compared to IBActions and IBOutlets on iOS, which allow you to drag and drop actions and references to files as you see fit, without needed to go through a generated file.

Now you should have something that looks roughly like this:

ih

The experience of setting this up in Android Studio is much better than it was in Eclipse. The IDE has a feature to hide a lot of the configuration files that you don’t need to worry about all the time and the visual preview works pretty well. Admittedly, the drag-and-drop visual editor functionality does not work so well, as it’s difficult to get your UI element into the view collection you want it to go in. Just like in Xcode with XML for UI, you have to open up the source file and modify it manually, however I get the impression that as I learn more Android there will be a lot more time spent manually writing XML than I ever spend on iOS, which is almost exclusively to resolve conflicts.

To perform the same path on iOS, download Xcode and start a new project. Go to the storyboard file and drop your UI elements into the square view. I recommend trying out stack views to do this, as they are a new feature with iOS 9 and they’re supposed to solve some of the pains with Auto Layout. Here’s what it ends up looking like:

Screen Shot 2016-02-26 at 6.42.46 AM

Android and iOS’s visual UI editors are in many respects equals. They both are XML editors and they both have quirks. I find the layout engine in iOS, Auto Layout, to be very powerful, but many people complain that it is difficult to use so I may just be experiencing Stockholm Syndrome.

Now that we have our UI finished, let’s write some code. The next step is to hook up our buttons to fire off a UI element which indicates to the user whether or not the answer they chose is correct. On Android, you get a reference to a view object from XML by asking your activity to find the view with an ID you set in the XML file. Like so:

this.mTrueButton = (Button) this.findViewById(R.id.true_button);
this.mFalseButton = (Button) this.findViewById(R.id.false_button);

While I like that generated resource file for the images and strings, I must say, I find this a very convoluted way of getting an association between a serialized view and an activity. If this were iOS and you wanted to get a view in your view controller, you could just directly map over a reference. But this isn’t so bad. Now that we have the buttons, it’s time to give them behaviors by setting their on click listeners:

this.mTrueButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(QuizActivity.this,
                R.string.correct_toast_text,
                Toast.LENGTH_SHORT).show();
    }
});

this.mFalseButton.setOnClickListener(new View.OnClickListener() {
    @Override
    public void onClick(View v) {
        Toast.makeText(QuizActivity.this,
                R.string.incorrect_toast_text,
                Toast.LENGTH_SHORT).show();
    }
});

Note that the on click listeners are a property on the button which you define the behavior of by creating an anonymous inner class. This is a cool way of getting block-like behavior and syntax out of Java. Also, a “toast” is an Android UI element which shows up briefly towards the bottom of the screen and contains some text.

To perform this same operation on iOS, open up your storyboard and view controller side-by-side by Alt-clicking in Xcode. Then, control-click-and-drag from the UI element you want a reference to from the storyboard into the view controller file, and select that you want an IBAction, which is like an on-click listener. You can make one for each button, or if you want to get clever you can make multiple buttons to the same IBAction and determine what to do at runtime. While iOS has no native notion of toast, I’ve hacked together one using UIAlertController and Grand Central Dispatch for sake of parity.

class ViewController: UIViewController {
    @IBAction func buttonTouchUpInside(sender: AnyObject) {
        guard let sender = sender as? UIButton else { return }
        let title = sender.titleLabel?.text == "True" ? "Correct!" : "Incorrect!"
        let alert = UIAlertController(title: title, message: "", preferredStyle: .Alert)
        self.presentViewController(alert, animated: true) { () -> Void in
            let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(1 * Double(NSEC_PER_SEC)))
            dispatch_after(delayTime, dispatch_get_main_queue()) {
                alert.dismissViewControllerAnimated(true, completion: nil)
            }
        }
    }
}

This code conditionally unwraps the sender into a button, and if it is a button, checks to see if it’s title is “True” to build the “Correct!” or “Incorrect!” text to display to the user. To do this, it uses a UIAlertController with that title, presents it, and when presentation is complete it waits 1 send to subsequently dismiss this alert controller.

Swift is truly magnificent. That code block above is not a snippet, that’s the whole view controller. In Android and Java and an Activity, the whole thing becomes quite long and nested fairly quickly. It does seems that if you’re going to use anonymous inner classes and getting views by IDs, however, you have to place it in a non-top-level function somewhere.

This is just a very thin top-to-bottom slice of the development for both Android and iOS. Admittedly, I prefer iOS development on account of its new language Swift and less cumbersome SDK, but this comes at the cost of not supporting older platforms and less ubiquitous third party libraries and community discussion (which Java has plenty of). Although perhaps soon they’ll be the best of both worlds, as it was recently proposed that Swift should get Android support!

Let's Build – A shared economy app – Wireframing

In this series of posts, I’m going to learn how to plan and build a shared economy web app. This is an opportunity to learn and document the process of wireframing, designing, and developing an application from nothing, which (crucially) is usable by real people. I’ll be drawing from Michael Hartl’s Ruby on Rails Tutorial to learn how to build the application. The idea that I’m going to be building out is simple. AirBnb lets you monetize your extra room, Uber lets you monetize your time and car, but what about that pool you have? Or your trampoline? Or your basketball net? So that’s it, a shared economy app for use of your extra amenities.

This post is dedicated to wireframing. In programming and in life, I’ve always found that coming up with a plan before doing something greatly increases the chances of success. When the luxury of a plan can be afforded, it’s advisable to indulge. In the case of building a web app with Rails, the plan should come in the form of a wireframe. A wireframe is a technical document which contains no color, font, or even layout decisions, but rather the structure of information and the architecture of how a user navigates an app.

In order to accomplish this, I purchased the Omni Group’s well-known and quite renowned OmniGraffle software. There were cheaper options out there, with the standard variant of OmniGraffle costing $99.99. Many people I trust use it and I enjoy high-quality Mac apps, so I took the plunge. You can likely accomplish this task with many other tools out there, free or otherwise, just search Google for “wire framing software” and do your research. Honestly, I find many things frustrating about OmniGraffle, but it’s treating me pretty well (I’ll perhaps write a review).

The next tool I’ll need to start wire framing is a good stencil (template) for OmniGraffle. To make my life easier in development, I’m going to use the Bootstrap front-end UI framework, so I found a stencil which has Bootstrap’s elements and grid. With these tools, you can drag-and-drop UI elements into you canvas to mock how your application will work. First, I created what my application will look like to the general public, for those customers who are seeking a pool (as opposed to listing one).

user-facing

Here, I tried to come up with the absolute minimum number of pages for users to have the core experience of this app – going online, inputing what they want to do, finding results of people who are offering to share their stuff, and checking out on it. I also tried to structure the information in a way that would make designing the application easy, in the sense that I avoided forms and used pictures liberally. Also, note that I’ve made a number of simplifications for the sake of this demonstration, for instance real users would want to refine by their location, I feel it’s just more than I’d like to get into for this learning experience.

After I finished these wireframes I realized I was missing something crucial. Users could easily find something they want to do, but it was impossible for them to post something they wanted to do. In wireframing this, I kept in mind that this user will tolerate something that doesn’t look too pretty, as long as it was efficient at getting their item up on the service. Furthermore, they are going to want a way to tracking how much money they’ve made. This differs from the customer-facing wireframe because it will not make liberal use of pictures and might be quite form-heavy, considering it’s data input. Here’s what I came up with:

admin-facing

With a quick idea, a good wire framing app, and a couple sessions at a coffee shop, I have a plan to take to the terminal. In the next post, I’ll either design the application by giving it some nice fonts and colors, or I’ll just jump into development (depending on my mood and level of impatience).