Over a million developers have joined DZone.

What 2015 Taught Us About iOS Development

The year 2015 is over and 2016 has already started with new projects and new ideas. It's high time to look back and revisit all of the good solutions that helped us in 2015. This summary will not be short, as there are quite a lot of things that were really useful.

· Mobile Zone

The year 2015 is over and 2016 has already started with new projects and new ideas. It's high time to look back and revisit all of the good solutions that helped us in 2015. This summary will not be short, as there are quite a lot of things that were really useful.

Fastlane

At the beginning of every iOS project, we set up Continuous Integration and Deployment. It includes several tasks, such as: installing dependencies, running tests, packaging an application, and submitting it to iTunes/Testflight. This process could be much more complicated, if we were not using Fastlane.tools. They are seriously amazing. The following are the most common pieces of our setup in Fastfile:

before_all do
  cocoapods
  scan
end

# Increment build number to current date
lane :set_build_number do
  increment_build_number(
     build_number: Time.new.strftime("%Y.%m.%d.%H%M")
   )
end

lane :beta do |beta|
  match
  set_build_number
  configuration = beta[:configuration] || "Release"
  gym(configuration: configuration)
  pilot(skip_submission: true)
end

In less than 20 lines of code we:

  • Install dependencies
  • Run tests
  • Fetch certificates and provisioning profiles from the internal repo, automatically managed by match
  • Generate and set the build number from the current time
  • Package .ipa file using gym
  • Upload .ipa to TestFlight

And, what's even more impressive is that all these tools are intelligently linked together to work seamlessly. So, if you need to generate screenshots for your app, update a changelog, or wait while a build is processing, you'll be working with the same tools, because Fastlane just seems to cover all possible aspects of continuous deployment you could think of. We seriously can't wait for the next tool that Felix Krause will hopefully develop.

IBInspectable

Having well-written code in an app is nice. But, do you know what's nicer? Not having to write code at all. IBInspectable is an incredibly cool feature of Interface Builder, that allows us to write significantly less code than before. For example, sometimes we need to make a button with borders and cornered layers. Sometimes we may need a rounded image. Having just a single extension on UIView we are able to achieve that without subclassing anything:

extension UIView {
    @IBInspectable var cornerRadius: CGFloat {
        get { return layer.cornerRadius }
        set {
            layer.cornerRadius = newValue
            layer.masksToBounds = newValue > 0
        }
    }

    @IBInspectable var borderWidth: CGFloat {
        get { return layer.borderWidth }
        set { layer.borderWidth = newValue }
    }

    @IBInspectable var borderColor : UIColor {
        get { return UIColor(CGColor: layer.borderColor ?? UIColor.whiteColor().CGColor }
        set { layer.borderColor = newValue.CGColor }
    }
}

This extension works for all UIView subclasses, not just UIButton or UIImageView. You won't see those changes in a xib or a storyboard, because we're not using IBDesignable here. However, completely dropping the subclassing requirement seems good enough. Less code = win.

Views, Loadable From XIB

This is not something new, but somehow we stumbled upon this solution only in 2015. And, it completely blew us away! The task is simple—we have a storyboard that contains a view that we want to design in a separate XIB and then just drop a UIView on our storyboard, set its class, and have it automatically loaded from another XIB file. Wouldn't that be cool? It turns out it's actually a simple thing to do, here's our tip:

protocol NibDefinable {
    var nibName: String { get }
}

extension NibDefinable {
    var nibName : String {
        return String(self.dynamicType)
    }
}

class LoadableFromXibView: UIView, NibDefinable {

    @IBOutlet weak var view : UIView!

    override init(frame: CGRect) {
        super.init(frame: frame)
        xibSetup()
    }

    required init?(coder aDecoder: NSCoder) {
        super.init(coder: aDecoder)
        xibSetup()
    }

    func xibSetup() {
        view = loadViewFromXib()
        view.frame = bounds
        view.autoresizingMask = [.FlexibleWidth, .FlexibleHeight]
        backgroundColor = .clearColor()
        addSubview(view)
    }

    private func loadViewFromXib() -> UIView {
        let bundle = NSBundle(forClass: self.dynamicType)
        let nib = UINib(nibName: nibName, bundle: bundle)
        let view = nib.instantiateWithOwner(self, options: nil).first as! UIView
        return view
    }
}  

Setup for these kinds of views is straightforward:

  1. Create LoadableFromXibView subclass
  2. Create a xib file, set the File's owner as your subclass
  3. Drag outlets and design your view as usual

These views can be created from code, loaded to a storyboard and a xib in any way you want. All you need is to set a class for UIView in your storyboard.

Although everything sounds simple, it turns out that this approach saves us an incredible amount of time and provides our views with wonderful reusability. It is sometimes common to design UITableViewCells and UICollectionViewCells as a composition of loadable views that can be reused elsewhere.

Swift

Swift is controversial. When it was released in June 2014 in beta, it was very unstable. In fact, it was still unstable one year later when Apple announced Swift 2. And really, it is still unstable now, constantly crashing code highlighting, compiler, and even XCode. However, Swift 2.1 is much more stable than Swift 1.2. So, we hope that we'll be working in a stable IDE once again in Spring 2016, when Swift 2.2 is released with all of these awesome fixes.

But, even now code in Swift is much shorter than in Objective-C. It provides us with an ability to work with types directly using Generics. It has awesome features like associated types, protocol extensions, and default implementations. While Swift lacks in runtime a bit, it still completely beats Objective-C in compile-time knowledge about variables, types, and expressions.

Optionals can be a source of frustration for developers moving from Objective-C. However, once you let them sink in, you start to understand why it's always necessary to understand when a variable can be nil or when it never can become nil.

It's also much easier to declare protocols in Swift. It was simple in Objective-C as well, but there was rarely an idea to use protocols as traits or mixins as in Ruby, for example. Protocol-oriented programming is a powerful concept, that can change the way you code forever.

We bet big on Swift. 2015 was the last year we considered Objective-C as a language choice for a project. In 2016 we are moving to "Swift by default".

Stack Views

If protocol-oriented programming can change the way you write code, stack views can change the way you design interfaces on iOS. If you have the luxury of supporting iOS 9 only, go ahead and use UIStackViews. We still support iOS 8, so we needed to find a compatible solution, which was to go with TZStackView.

There are a lot of use cases for stack views, but the most common ones for us were building forms (e.g. sign up) and single content interfaces. For example, we may have a profile for a current user and a profile for another user. They consist of several common views that we want to reuse. However, in some places they are different, so we need to be able to compose them differently. And, here's where loadable views and stack views really help. Here is, for example, how current user profile views are created:

let stacks = [UserProfileStatsView(), SwitchCompanyView(), SendInvitationToCompanyView(), LogoutButtonView()]

stackView.axis = .Vertical
stacks.forEach {
    stackView.addArrangedSubview($0)
}  

Of course, there's some more setup involved in how we bind data to these views, but notice how easily the interface is constructed. We don't have to worry about constraints amongst these views, because the stack view manages all of them automatically. We gain reusability and flexibility. If we need to add or remove some views from a view controller, it's simply about removing a stack from the stack view. We don't have to go and undo all constraints from a view controller and create them from scratch.

One thing to remember, though, is that Stack View is not a replacement for UITableView or UICollectionView. If you have a lot of repetitive views horizontally or vertically, it's much easier to use UITableView or UICollectionView. The stack view really rocks only if you have an interface with several different views.

Tools

While architectural and design solutions are great, you really need the best tools available to be able to do your work efficiently. And, here's our list of top tools we used in 2015:

Alamofire + AlamofireImage

AFNetworking was a long time king for networking on iOS. However, it became bloated and was buried under hundreds of issues. It was not really nice to Swift’s type system as well, so we started to look for a replacement. And, we found that Alamofire and AlamofireImage are really the answer to all of our questions. These frameworks are the best stuff that existed in AFNetworking, completely rebuilt and rethought to bring a Swifty experience to networking. Maintained by Alamofire Software Foundation, they have great test coverage, incredible tech support, and a very low amount of open issues. Alamofire allows powerful usage of Swift generics, which helps to build a type-safe response and error parsing.

Moving AlamofireImage to a separate repository was a very good decision. It contains very well-structured code with an incredible amount of features AFNetworking extensions could only dream of. These are single and multi-pass image filters, auto purging cache, image transitions, download queues, and much more.

SwiftyJSON

Let's face it. Everyone is writing his/her own JSON parser in Swift. And while some of them are interesting, like Argo, most of the others are just a mess with operator overloads that really do not solve any problems. However, SwiftyJSON does. It is really the best and the safest way to work with JSON in Swift, and there's really almost no reason to search for something else.

FuzzyAutocomplete

Writing code is what we do every day. And to do it quickly, you really need tools to boost your productivity. FuzzyAutocomplete plugin for XCode is one of them. It should really be preinstalled with XCode.

CocoaPods

2016 will be a year of competing package managers on iOS. CocoaPodsCarthageSwift Package Manager... we don't know which one will be more robust and commonly-used, but 2015 was really a year of CocoaPods. This incredible package manager allows installing dependencies in just one line of code. And, support for dynamic frameworks is great if you work with Swift.

2016

2015 was an interesting year for iOS development. We'll remember our sadness every time when DerivedData messed up our build. We'll remember the happiness of looking at beautifully organized generic Swift code, that we continue to reuse in every project we write. And most importantly, we do always remember the joy when some new technology or approach changes our code style forever.

Stay hungry. Stay foolish. Good luck to all of you in 2016!

MLSDev Blog

Topics:
ios ,ios development ,mobile ,mobile development ,swift ,cocoapods ,fastlane

Published at DZone with permission of Denys Telezhkin, DZone MVB. See the original article here.

Opinions expressed by DZone contributors are their own.

The best of DZone straight to your inbox.

SEE AN EXAMPLE
Please provide a valid email address.

Thanks for subscribing!

Awesome! Check your inbox to verify your email so you can start receiving the latest in tech news and resources.
Subscribe

{{ parent.title || parent.header.title}}

{{ parent.tldr }}

{{ parent.urlSource.name }}