Version

Other, Other, Other

Finished Weather App

Every developer has their own ideas as to the best way to create top-notch iOS apps. Some developers take advantage of Auto-Layout, some like to create all of their graphics in code, and some developers even like to code in Vim!

With the recent release of iOS 7 and Xcode 5, I thought it would be a great time to provide a case study using a unique set of approaches and tools to create a basic weather app; you can look upon these as my recommended iOS 7 best practices. The first stepping-stone to iOS development used to be building a Todo List app. However, as iOS has matured new iOS developers are expected to be proficient in modern techniques such as data management and consuming web requests.

In this 2-part tutorial series, you’ll explore how to create your own apps using the following tools and techniques:

This tutorial is designed for intermediate-level developers who know the basics, but haven’t moved into too many advanced topics. This tutorial is also a great start for anyone wanting to explore Functional Programming in Objective-C.

Getting Started

You now have your base project set up. The next step is to set up your third-party tools — but first make sure you close Xcode so it won’t interfere with the next steps.

Cocoapods

You’ll be using Cocoapods to take care of downloading the code, adding files to your Xcode project, and configuring any project settings that those projects require. Let’s first cover what projects you’ll be using.

Mantle

Mantle is a project by the Github team that helps remove all of the boilerplate code that Objective-C requires to turn JSON data into NSObject subclasses. Mantle also does value transformation, which is a fancy way to turn JSON primitive values (strings, ints, floats) into complex values like NSDate, NSURL, or even custom classes.

LBBlurredImage

LBBlurredImage is a simple project that extends UIImageView and makes blurring images a breeze. You’ll be creating a fancy blur with just a single line of code. If you’re interested in seeing how the blur works, check out the source code.

TSMessages

TSMessages is another wonderfully simple library that takes care of displaying overlay alerts and notifications. When presenting error messages that don’t directly impact the user, it’s better to present an overlay instead of a modal view (like UIAlertView) so that you irritate the user as little as possible.

You’ll use TSMessages when a network connection is lost or the API encounters some other error. If something were to go wrong, you’d see an overlay like the one below:

ReactiveCocoa

The last library you’ll use is ReactiveCocoa, also made by the Github team. ReactiveCocoa brings functional programming to Objective-C by following patterns introduced by Reactive Extensions in .NET. You’ll be spending a good portion of your time in Part 2 implementing ReactiveCocoa.

Setting Up Your Cocoapods Libraries

To set up your Cocoapods libraries, first ensure that you have Cocoapods installed. To do that, open the Terminal application, type the following, and hit Enter.

which pod

You should see something similar to the following output:

/usr/bin/pod

Depending on how you manage your Ruby gems, for instance if you use rbenv or RVM, then your path may differ.

If the terminal simply returns to the prompt, or states pod not found, Cocoapods isn’t installed on your machine; check out our tutorial on Cocoapods for installation instructions. It’s also a great resource if you just want to learn more about Cocoapods.

Podfiles are used to tell Cocoapods which Pods, or open-source projects, to import.

To create your first Cocoapod, first use the cd command in Terminal to navigate to the the folder where you saved your Xcode project. Launch the Pico editor by entering the pico command in Terminal.

Cocoapods will create a bunch of new files in your project directory; however, the only one that you’ll be concerned about is SimpleWeather.xcworkspace.

Open SimpleWeather.xcworkspace in Xcode. Take a look at your project setup; there’s now a Pods project in the workspace, as well as folders for each of the libraries you imported in the Pods folder, like so:

Make sure you have the SimpleWeather project selected, as shown below:

Build and run your app to make sure everything is working properly:

It doesn’t look like much right now, but you’ll add some content shortly.

Note: You might notice a few projects have build warnings. Projects imported with Cocoapods are made by many different developers, and different developers have different tolerances for build warnings. Most of the time you should be able to ignore them. Just make sure there are no compiler errors!

Creating Your Main View Controller

Although the app looks complex, it will be powered by a single view controller. You’ll add that now.

With the SimpleWeather project selected, click File\New\File and select Cocoa Touch\Objective-C class. Name your class WXController and make it a subclass of UIViewController.

Make sure that both Targeted for iPad and With XIB for user interface are both unchecked, as shown below:

Open WXController.m and replace the boilerplate -viewDidLoad method with the following:

Sharp-eyed readers will note that WXController is imported with quotes, while TSMessage is imported with angle brackets. What gives?

Look back to when you created the Podfile; you imported TSMessage with Cocoapods. Cocoapods created the TSMessage Pod project and added it to your workspace. Since you’re importing from other projects in the workspace, you use angle brackets instead of quotes.

Replace the contents of -application:didFinishLaunchingWithOptions: with:

Initialize and set the WXController instance as the application’s root view controller. Usually this controller is a UINavigationController or UITabBarController, but in this case you’re using a single instance of WXController.

Set the default view controller to display your TSMessages. By doing this, you won’t need to manually specify which controller to use to display alerts.

Build and run to see your new view controller in action:

The status bar is a little difficult to read against the red background. Fortunately, there’s an easy way to make the status bar a lot more legible.

There’s a new API in UIViewController in iOS 7 to control the appearance of the status bar. Open WXController and add the following code directly below -viewDidLoad:

Build and run again and you’ll see the following change to the status bar:

Setting Up Your App’s Views

It’s time to make your app come to life. Download the images for this project here and unzip them to a convenient location. This package contains a background image by Flickr user idleformat and weather icons by Dribbble user heeyeun.

Note: The background image is of San Francisco since the iPhone Simulator defaults its geolocation to that city. If you want to personalize your app, feel free to substitute an image of your own hometown — or any image you choose, for that matter.

Switch back back to Xcode and click File\Add Files to “SimpleWeather”…. Locate the Images folder you just unzipped and select it. Check the Copy items into destination group’s folder (if needed) option and click Add.

Open WXController.h and add the following delegate protocols directly below the @interface line:

<UITableViewDataSource, UITableViewDelegate, UIScrollViewDelegate>

Now open WXController.m. Protip: you can use the hotkey Control-Command-Up to quickly toggle between the .h and .m files.

Add the following import to the top of WXController.m:

#import <LBBlurredImage/UIImageView+LBBlurredImage.h>

LBBlurredImage.h is contained in the LBBlurredImage project you imported with Cocoapods; you’ll use this library to blur your background image.

There should be an empty private interface boilerplate for WXController beneath the imports. Fill it in with the following properties:

Now it’s time to create and set the views in your project. “But wait,” you say. “Where are the IBOutlets?”

Be forewarned: all of the views are created and set up… in code! :]

Hang on — don’t freak out just yet. There are lots of ways to create views, and everyone has their favorite. We even held a debate on the RayWenderlich.com team on the different styles and what each person prefers. Storyboards, NIBs, and code all have their pros and cons.

The views in this app aren’t terribly complicated and don’t necessarily have the performance hit that Auto-Layout can cause. However, since this is a case study, you’ll stick to using code.

You’ll create three views and stack them on top of each other to create the effect that you saw in the GIF at the beginning of this tutorial. Here’s an exploded view of what you’ll make, bearing in mind that the table view will be transparent:

To provide the dynamic blur effect, you’ll change the alpha of the blurred image as you scroll through your app.

Open up WXController.m and replace the code in -viewDidLoad that sets the background color with the following code:

Get and store the screen height. You’ll need this later when displaying all of the weather data in a paged manner.

Create a static image background and add it to the view.

Create a blurred background image using LBBlurredImage, and set the alpha to 0 initially so that backgroundImageView is visible at first.

Create a tableview that will handle all the data presentation. WXController will be the delegate and data source, as well as the scroll view delegate. Note that you’re also setting pagingEnabled to YES.

Add the following code for the UITableView delegate and data source to the @implementation block of WXController.m:

That’s quite a chunk of code, but it’s really just doing the heavy lifting of setting up the various controls in your view. In short:

Set the current-conditions view as your table header.

Build each required label to display weather data.

Add an image view for a weather icon.

Build and run your app; you should see all of your views laid out before you. The screenshot below shows all of the labels along with their frames for a visual on manual layout:

Give the table a nudge with your finger; it should bounce when you scroll it.

Retrieving Weather Data

You’ll notice that the app says “Loading…“, but it’s not really doing anything. Time to get some real weather conditions.

You’re going to pull data from the OpenWeatherMap API. OpenWeatherMap is a really awesome service that aims to provide real-time, accurate, and free weather data to anyone. There are a lot of weather API’s out there, but most of them either use older data formats like XML, or they are paid services — and sometimes quite expensive.

In this case, the dictionary key is WXCondition‘s property name, while the dictionary value is the keypath from the JSON.

You may have noticed that there’s a glaring issue with the way the JSON data is mapped to the Objective-C properties. The property date is of type NSDate, but the JSON has an NSInteger stored as Unix time. You’ll need to convert between the two somehow.

Mantle has just the feature to solve this problem for you: MTLValueTransformer. This class lets you declare a block detailing how to convert to and from a value.

The syntax for using Mantle’s transformers is a little strange. To create a transformer for a specific property, you add a class method that begins with the property name and ends with JSONTransformer.

It’s probably easier to see it in context than to try and explain it, so add the following transformers for NSDate properties to WXCondition.m.

You return a MTLValueTransformer using blocks to transform values to and from Objective-C properties.

You only need to detail how to convert between Unix time and NSDate once, so just reuse -dateJSONTransformer for sunrise and sunset.

This next value transformation is a little annoying, but it’s simply a consequence of using OpenWeatherMap’s API and the way they format their JSON responses. The weather key is a JSON array, but you”re only concerned about a single weather condition.

Using the same structure as -dateJSONTransformer in WXCondition.m, can you create a transformer between an NSArray and NSString? The solution is provided below if you can’t quite get it on your own.

Where To Go From Here?

In this part of the tutorial, you set up your project with Cocoapods, added views to the controller, laid out those views and built models to reflect the weather data you will be fetching. The app still isn’t fully functional, but you’ve survived creating views directly in code, and learned how to map and transform JSON data using Mantle.

Next check out part 2 of this tutorial, where you’ll flesh out your app to fetch data from the weather API and wire up your UI. You’ll be using the new iOS 7 NSURLSession to download data along with ReactiveCocoa to tie together the location finding, weather fetching, and UI updating events.

If you have any questions or comments, please share them with us in the forums!