How to Style Your iOS App with NUI

Intro

NUI is one of the few handy open-source libraries that allow iOS apps to be styled, much like websites through CSS. This allows for developers and designers alike to quickly make changes in a CSS file to adjust the appearance of various UI components in your app. No more dealing with the cumbersome UIAppearance and having to dig through code to make changes. This allows for the nontechnical people on your team to directly tweak and fiddle with the app to their hearts’ content, leaving us developers to concentrate on the more important aspects of the app. 😉

There was Pixate (changed trajectory and was acquired by Google), UISS (inactive), and Nimbus (feature development inactive). However, NUI is the only one that managed to stand the test of time, is actively developed, and reasonably popular (3382 stars at the time of this writing). I have used NUI in a few projects I work on and really love its power. I’m not going to lie, it is quite an investment to setup and maintain throughout your project, but really pays off long-term. In this post I cover how to get up and running with NUI.

Walkthrough

Here is the initial commit of the sample project I used in this walkthrough. You can feel free to follow along.

Getting Started

First consult the installation section in NUI’s Readme. You can install the manual way or through CocoaPods, pick your poison. If you are installing through CocoaPods you need to add pod ‘NUI’, ‘~> 0.5’ to your Podfile before hitting your terminal with a pod install.

Protip!

If CocoaPods just created a .xcworkspace file for you and spit out this bit of advice:

[!] Please close any current Xcode sessions and use `NUITestApp.xcworkspace` for this project from now on.

Close out of your project and reopen from the workspace before proceeding.

Add the following to your AppDelegate file:

#import <NUI/NUISettings.h>

// ...

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions {
    // Override point for customization after application launch.

    [NUISettings init];  

    return YES;
}

Building and running should display something like so:

Screen Shot 2015-12-30 at 3.55.14 PM

If you don’t have a problem with building an ugly looking app, you are pretty much done, but if you actually want to make something that is appealing to the eyes, read on!

Customization

If you take a look at NUI’s init method, you’ll see this:

+ (void)init 
{
    [self initWithStylesheet:@"NUIStyle"];
}

It can be deduced from this that in order to use a style sheet of your own you need to call NUI’s  initWithStylesheet: method. Well let’s get to it then, ey?

Create a new empty file and give it a cool, hipsteresque name like CartmanBrah.nss, or if you want to be boring like all other developers in the iOSphere you can give it a “proper” name, like MyProperlyNamedStyleSheet.nss.

Protip!

Be sure to set the extension of the file to .nss as that is what NUI expects the extension of the style file to be.

Change the NUI init method to specify the new file you created:

[NUISettings initWithStylesheet:@"CartmanBrah"];

Adding a NUI Element from a Storyboard

Let’s lay down some styles in that new file, ey? (No, I’m not Canadian, I just really like saying ‘ey’). Put something like this in your newly-created style sheet:

FirstTabBar {
    font-name: italicSystem;
    font-size: 18;
    font-color: orange;
}

Head over to the storyboard file and add the following line to the User Defined Runtime Attributes of the first view’s UITabBarItem:

nuiClass string FirstTabBar

You should end up with something like this when finished:

Screen Shot 2015-12-30 at 7.39.54 PM

Adding a NUI Element Programmatically

Let’s specify the nui class for the other tab bar item programmatically. Go back to your style sheet and add the following to it:

SecondTabBar {
    font-name: boldSystem;
    font-size: 13;
    font-color: red;
}

Head on over to SecondViewController.m and add the following to it:

#import <NUI/UITabBarItem+NUI.h>

// ...
- (void)awakeFromNib {
    [super awakeFromNib]; 

    self.tabBarItem.nuiClass = @"SecondTabBar";
}

Conclusion

Setting the nuiClass property of an object specifies which style object in your stylesheet the object should conform to. As seen above, this can be done via xib/storyboard or programmatically. To see which properties are supported for various objects, consult the Style Classes section of the NUI Readme. And here is the repository for the finished sample project.

Build and run the app and you should see something like so:

Screen Shot 2015-12-30 at 9.21.19 PM

And there you have it — iOS application styling via style sheets!

How Use AppUpdateTracker To Detect Install/Update Behavior in Your iOS App

Have you ever needed to determine which version of your app users are updating from for data migration purposes? Or perhaps you want to determine the time at which the user opened your app for the first time for analytics purposes? Well, there is an app, er… library for that: AppUpdateTracker.

AppUpdateTracker was created initially as some cobbled code I hastily added within the source of Appirater while working on the UCD Mobile project. I needed the ability to determine not only when the user updated the app, but from which version they are upgrading for in order to perform data migrations within the Core Data store.

I extracted that code into an isolated project and thus, AppUpdateTracker was born. It detects the following events:

  • when the user launches the app for the first time, provides:
    • timestamp of when user opened app for the first time, in seconds since epoch
    • installation count representing the number of times the user has opened the app for the first time on the same device
  • when the user opens the app for the first time after updating, provides:
    • the previous version the user updated from
    • the current version of the app (provided for convenience)
  • when the user brings the app to the foreground, provides:
    • usage count representing how many times the app has been opened (includes bringing app to foreground after resigning active, not only cold start)

It works by persisting a small amount information within NSUserDefaults, all of which are directly accessible via getters in the interface. It broadcasts an NSNotification whenever one of the 3 aforementioned events occurs. It is important to note that only 1 event can happen during any given app session, so you needn’t worry about handling the case where an app update notification is broadcast, followed by that of a use count incremented. (The use count is reset to 1 in this case.)

Additionally, I have recently added block support, making usage trivial:

[AppUpdateTracker registerForAppUpdatesWithBlock:^(NSString *previousVersion, NSString *currentVersion) {
        NSLog(@"app updated from: %@ to: %@", previousVersion, currentVersion);
}];
[AppUpdateTracker registerForFirstInstallWithBlock:^(NSTimeInterval installTimeSinceEpoch, NSUInteger installCount) {
        NSLog(@"first install detected at: %f amount of times app was (re)installed: %lu", installTimeSinceEpoch, (unsigned long)installCount);
}];
[AppUpdateTracker registerForIncrementedUseCountWithBlock:^(NSUInteger useCount) {
        NSLog(@"incremented use count to: %lu", (unsigned long)useCount);
}];

Which you are free to call anywhere or anytime within your app (although it is recommended you call these within application:didFinishLaunchingWithOptions:), resulting in one and only one of the 3 blocks being called during any given session (with the exception of registerForIncrementedUseCountWithBlock: being called every time the app is foregrounded).

So there you have it! Easy app update/install tracking for your iOS app. Enjoy!