Rebuilding the new Buienradar iOS App

The new Buienradar App is now available for download in the App Store here.

The last few months I’ve been very busy building the new Buienradar iOS app. It was build before entirely in Objective-C, had some redesigns and the codebase was getting full of extensions on top of the base application. It was time to rebuild for the future, make it future proof, in other words, rebuild it in Swift.

Rebuilding the biggest weather app of the Netherlands, the New Buienradar iOS App

Rebuilding the biggest weather app in the Netherlands comes with responsibilities. An application with over 1.5 million users needs to be updated smoothly without any troubles. It made choosing the right, stable frameworks very important for the new Buienradar iOS app.

Choosing the right frameworks

As the old app was build with frameworks like AFNetworking and SDWebImage, it was easy to go ahead with these again as they proved stability. However, we wanted to build a future proof app build in Swift, so I explored Github to find myself some new fresh Swift frameworks to use.

Networking

As I’m a big fan of ReactiveCocoa (it has a Swift version already) and I’m using it a lot, I came across Moya. Define your API inside an enum, use the subspec Moya/ReactiveCocoa and you’re ready to go. It uses Alamofire, which is the Swift version of AFNetworking.

One thing I missed inside Moya was mapping JSON to objects. Therefor I created Moya-SwiftyJSONMapper, which resulted in API calls like this:

let signalProducer = BuienradarAPI.LocationForecast(locationId: locationId)
    .request()
    .mapResponseToObjectOfType(BRLocationForecast)
    .mapToNextFourteenDaysForecast()
    .observeOn(QueueScheduler.mainQueueScheduler)
    .onNext { [weak self] (daysForecast) -> () in
        self?.forecastGraphView.configureWithDaysForecast(daysForecast)
        self?.addWidgetsForDaysForecast(daysForecast)
    }
    .attachToDataRequestView(dataRequestView!)
    .attachToSignalProducerReloader(foregroundReloader, reloadAction: foregroundReloadAction)

signalProducer.start()

Notice the extensions made on top of ReactiveCocoa like attachToDataRequestView and attachToSignalProducerReloader. I’ll get back to those soon.

Swift Image Library

As I was very familiar with SDWebImage, choosing a different image library felt like a big change. I came across Kingfisher, which had his inspiration from SDWebImage and therefor made it an easy switch.

By creating a RAC extension (check it out here), image calls ended up like this:

KingfisherManager.sharedManager.rac_retrieveImageWithURL(spriteImageURL,
    optionsInfo: [KingfisherOptionsInfoItem.CacheMemoryOnly, .ForceRefresh],
    progressBlock: { [weak self] (receivedSize, totalSize) in
        // Handle progress
    }).onError({ (error) in
        // Error
    }).onNext({ (image, cacheType, imageURL) in
        // Set image
    }).start()

Handling the unhappy flow

.attachToDataRequestView(dataRequestView!)

Something I wanted to take care of from the very beginning was the unhappy flow. Together with ReactiveCocoa, Moya and my own created library ALDataRequestView, this was very easy.
The framework comes with the following dataSource methods:

func loadingViewForDataRequestView(dataRequestView: ALDataRequestView) -> UIView?
func reloadViewControllerForDataRequestView(dataRequestView: ALDataRequestView) -> ALDataReloadType?
func emptyViewForDataRequestView(dataRequestView: ALDataRequestView) -> UIView?

As the app is build with a widget system, every widget gets it’s own ALDataRequestView:

ALDataRequestView examples

ALDataRequestView examples

The example shows the loading and failed states, where it also has a successful and empty state. More info can be found on the Github page: ALDataRequestView

Reloading data

.attachToSignalProducerReloader(foregroundReloader, reloadAction: foregroundReloadAction)

The other thing I’ve used are reloaders. I’ve created several, but the foreground reloader is the most used (it can be found here). You can use it manually or attach it to a signalproducer and it will call the reload action when the app get in the foreground again after the seconds interval.

let foregroundReloader = ForegroundReloader(secondsInterval: AppConstants.refreshInterval)

Finishing up

At the end, we’ve finished up with around 1500 beta testers. Starting with over 7000 sessions and 80 crashes, we’ve ended up with the final TestFlight build which had 3000 sessions and zero crashes. On top of that, many users responded with feedback which made the app much better and ready to replace the old one.

Check it out yourself and download the app here

 

Antoine van der Lee

Dutch iOS developer at Triple. Developed apps like Buienradar, Videoland and Pop the Dots.

 

One thought on “Rebuilding the new Buienradar iOS App

Comments are closed.

Follow on Feedly