Universal Custom iOS UI with Swift

Let's say that we want our Swift app to have a custom Navigation Bar. The default iOS Navigation Bar is usually a light grey that's slightly translucent, with blue buttons. But we want ours to be a non-translucent orange, with white buttons and white text.

When you want to set a custom background color, font, or tint color for your UI element, your first thought might be to do this in your UIViewController, probably in the viewDidLoad(:_) function. However, once you do this for each view in your app, your code starts to have a lot of unnecessary repeated code just so your UI elements look the same. Some of you might think, "Well, you can just set custom properties in the Interface Builder for each element!" Still, you'd have to do this for each UI element in your app, and that could take a lot of time. Instead, we can set up our custom UI elements in the AppDelegate.swift file just once, and save ourselves a ton of time.

Setting Up

Start up Xcode and select Create a new Xcode Project. Under iOS>Application, select the option for Single View Application and click Next. On the next screen, fill in your desired Product Name, Organization Name, and Organization Identifier. Make sure that Swift is selected under Language, and iPhone under Devices. None of the checkboxes below should be selected. Click Next, and then Create on the next screen.

The View Controller

In the Project Navigator, you should see a few files have been created for you. Select the file named Main.Storyboard. There will be one blank View Controller on your storyboard. Click on its title, and make sure that the View Controller is selected in the Document Outline. Then, in the Xcode menu select Editor>Embed In>Navigation Controller. This will embed our View Controller inside a UINavigationController, which controls the navigation stack.

Next, select the Navigation Item under our View Controller in the Document Outline. In the Utilities Pane, select the baseball diamond at the top (also known as the Attribute Inspector, btw). Fill in the Title field with a name for your View Controller, I'm calling mine "CA View Controller". This will be displayed in the middle of our Navigation Bar when the app is running.

Then, at the bottom of the Utilities Pane, drag a Bar Button Item (if you have trouble finding it, you can type 'bar' in the filter at the bottom to help you out) from the Object Library to the right side of the Navigation Bar in your View Controller.

Back in the Attribute Inspector, under the field System Item, select Camera. This gives us a nice camera button image so we can see our custom button color when we run the app. Once you've added your button, your Storyboard should look like the one below.

And that's it for setting up our Storyboard!

Dealing with the App Delegate

Now, select the file named AppDelegate.swift. It's filled with lots of empty boilerplate code that we don't need to worry about. Yours should look something like this:


import UIKit

@UIApplicationMain
class AppDelegate: UIResponder, UIApplicationDelegate {

  var window: UIWindow?


  func application(application: UIApplication, didFinishLaunchingWithOptions launchOptions: [NSObject: AnyObject]?) -> Bool {
    // Override point for customization after application launch.
    return true
  }

func applicationWillResignActive(application: UIApplication) {
    // Sent when the application is about to move from active to inactive state. This can occur for certain types of temporary interruptions (such as an incoming phone call or SMS message) or when the user quits the application and it begins the transition to the background state.
    // Use this method to pause ongoing tasks, disable timers, and throttle down OpenGL ES frame rates. Games should use this method to pause the game.
  }

  func applicationDidEnterBackground(application: UIApplication) {
    // Use this method to release shared resources, save user data, invalidate timers, and store enough application state information to restore your application to its current state in case it is terminated later.
    // If your application supports background execution, this method is called instead of applicationWillTerminate: when the user quits.
  }

  func applicationWillEnterForeground(application: UIApplication) {
    // Called as part of the transition from the background to the inactive state; here you can undo many of the changes made on entering the background.
  }

  func applicationDidBecomeActive(application: UIApplication) {
    // Restart any tasks that were paused (or not yet started) while the application was inactive. If the application was previously in the background, optionally refresh the user interface.
  }

  func applicationWillTerminate(application: UIApplication) {
    // Called when the application is about to terminate. Save data if appropriate. See also applicationDidEnterBackground:.
  }


}

The function we're interested in is the first one, application(_:didFinishLaunchingWithOptions:). This is where we can add any UI customizations that we want to be applied application-wide. In our case, we want to set some of the properties for our custom Navigation Bar. So, in your application(_:didFinishLaunchingWithOptions:) add the following lines of code:


//sets the font color
UINavigationBar.appearance().titleTextAttributes = [NSForegroundColorAttributeName: UIColor.whiteColor()]

//sets the tint color, which dictates the button color
UINavigationBar.appearance().tintColor = UIColor.whiteColor()

//sets the Bar tint color
UINavigationBar.appearance().barTintColor = UIColor.orangeColor()

//sets the bar translucence property
UINavigationBar.appearance().translucent = false

Wrapping Up

And that's all there really is to it! Much simpler than setting up each View's navigation bar individually. Although we set up a UINavigationBar in our example, you can use this method with any UI element you can think of by just adding the .appearance() proxy. Now you can just build and run your app to see your beautiful custom Navigation Bar!