Categories
Blog

A better UIAppDelegate

One of the most common ugly patterns I see while reviewing iOS code is the overcrowding of the UIAppDelegate with calls for all kinds of services. It all starts with the CoreData stack setup code, then someone adds code to setup an analytics service, short followed by a Push Notification service, InApp Purchase, Crash Reporter, etc…

Before you notice it the AppDelegate gets hundreds of lines of unrelated code, hard to maintain and gets to be a central point of all dependencies. One simple pattern can help us to break this cycle: Delegation.

For each of the services create a controller class that represents that functionality and then delegate the necessary calls from the UIApplicationDelegate to the controller. Let’s see an example with the CoreData code.

Start by creating a Master-Detail Application projet using the XCode and select the CoreData option. You will get an AppDelegate with the following properties and methods:

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;

@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;

@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

- (void)saveContext;

Why do we need these methods to be were? We can be easily be moved them to a singleton class called DataController and then refer to it instead implementing them in the AppDelegate. The interface of this object can look like this:

@interface SEDataController : NSObject

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

+ (SEDataController *)sharedInstance;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;

But this will only solve part of the issue, we still have calls being made on the AppDelegate to the singleton. Instead of flooding the AppDelegate with calls on each delegate method we can make our controllers implement UIApplicationDelegate protocol.

@interface SVEDataController : NSObject 

@property (readonly, strong, nonatomic) NSManagedObjectContext *managedObjectContext;
@property (readonly, strong, nonatomic) NSManagedObjectModel *managedObjectModel;
@property (readonly, strong, nonatomic) NSPersistentStoreCoordinator *persistentStoreCoordinator;

+ (SVEDataController *)sharedInstance;
- (void)saveContext;
- (NSURL *)applicationDocumentsDirectory;</pre>
and then on the .m file we implement the UIApplicationDelegate methods that make sense for this service:
<pre>#pragma mark - UIApplicationDelegate

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    [self managedObjectContext];
    return YES;
}

- (void)applicationWillTerminate:(UIApplication *)application
{
    [self saveContext];
}

For this methods to work you need to refactor your AppDelegate in a way that it forwards the calls to available services

- (NSArray *) services {
    static NSArray * _services;
    static dispatch_once_t _onceTokenServices;
    dispatch_once(&amp;_onceTokenServices, ^{
        _services = @[[SVEDataController sharedInstance]];
    });
    return _services;
}

- (BOOL)application:(UIApplication *)application didFinishLaunchingWithOptions:(NSDictionary *)launchOptions
{
    id service;
    for(service in self.services){
        if ([service respondsToSelector:@selector(application:didFinishLaunchingWithOptions:)]){
            [service application:application didFinishLaunchingWithOptions:launchOptions];
        }
    }
}

As you can see we know have a service array that holds all of our services. These services can them respond to the UIApplicationDelegate selectors that are relevant for their execution.

You can now easily add more services, for more services  check the example project for SVEApplicationDelegate in github.

Categories
Blog

OCLint

While developing for iOS one of tools that I missed a lot from my C# projects  was FxCop. FxCop was a tool that analysed your assemblies and reports information about the assemblies, such as possible design, localization, performance, and security improvements.  On Xcode the only similar tools is the static analyser but it’s scope its limited to memory issues.

So it was with great excitment  that I found out about the OCLint project. As they say in their website

OCLint is a static code analysis tool for improving quality and reducing defects by inspecting C, C++ and Objective-C code and looking for potential problems

  • Possible bugs – empty if/else/try/catch/finally statements
  • Unused code – unused local variables and parameters
  • Complicated code – high cyclomatic complexity, NPath complexity and high NCSS
  • Redundant code – redundant if statement and useless parentheses
  • Code smells – long method and long parameter list
  • Bad practices – inverted logic and parameter reassignment

The documentation is excellent and it’s very simple to integrate it to Xcode or better yet to your Jenkins build server ( just missing a easy way to use it on Travis CI easily can someone provide a brew for it?).

My selected approach was using it with xctool but I need to tweak a bit the default values :(20 characters for a objective C variable name is a bit on the short side). Here is the script that I’m using at the moment for Xcode

For Jenkins I’m using this variation that allows to create PMD reports

Categories
Blog

Styling your app

One of the great challenges in iOS development is how to do the styling if your app in a easy maintainable way.
A lot of people start by doing it in their nib or storyboards directly, but they quickly find the limitations: no way to set custom fonts in your components, no way to refer any kind of global variables for things like background color or image, standard offsets etc…

My favourite approach at the moment is to set all these values by code on viewDidLoad methods using the help of category methods on UIFont, UIColor, UIImage, UIFont and others.

To help in more tricky styling I sometimes use the Paint Code App (Apple should copy some  of the ideas here to their IB editor)

Recently I found a very powerful alternative: Pixate. This tools is a iOS framework that allows you to style your interface using CSS files. It even allows download and applying of style files while the application is running! I’m seriously considering giving it a go it for my next project.

Categories
Blog

Fast Android Emulators

One of the big pains of Android development was the lack of a fast Android emulator to test apps. Until recently to do any kind of development you need to own a actual device and with the fragmentation on Android this could very expensive…

Say hello to GenyMotion a company that provide super fast emulators. They are based on Virtual Box  images done for Intel processors and they even support Google APIs.

Android programmers heaven!

Categories
Blog

Third Party Continuous Integration for iOS

Until recently if we wanted to have continuous integration for your iOS project we needed to create your own solution, normally it involved the creation of a Jenkins instance in a MacMini. Now with  Xcode 5 and the OSX Server we also have an official Apple alternative in the form of Xcode bots, but you still need fork for your own server.

Luckily in  the last months a lot of third party services are starting to appear that provide a good service, for private repositories and with decent prices.

  • Travis-CI, a big player in the open source projects, providing automatic building for thousands of projects in Github, it now has a commercial solution for private repositories. One of the big advantages is that it’s not limited to iOS you can build almost anything on it.
  • Buildozer.IO, a bit cheaper than Travis but only with support for iOS and Android projects.
  • MacBuildServer, still in the beta phase and only for open source projects.

 

Categories
Blog

CocoaDocs

The fine guys from CocoaPods now provide us CocoaDocs a tool to search and view documentation for most  the libraries that are available in their pods repository.

The best thing is that if you have a library and its configured to to be a cocoapod the documentation is automatically generated for you.

The index page is base on the Readme.md file in the repository and the class documentation is generated from the code comments in you classes.

You just need to follow the AppleDoc syntax.

 

Categories
Blog

YouTube Videos

Until recently to display YouTube videos in iOS or Android you need to use or an external player or some kind of Web view. The first approach made users leave your app and the second one normally was slow and buggy.

Recently Google finally launched an YouTube Player API for Android.

Unfortunately there isn’t a version for iOS but some nice fellows developed LBYouTubeView. This component is a MPMediaPlayerController subclass that is capable of displaying YouTube videos URL. It manages this by requesting information of the video from YouTube and then getting an URL to the media stream that can be played using a MPMediaPlayerController. Not sure if it’s 100% reliable and legal but it does the job!

Categories
Blog

The missing Xcode plugin manager

Alcatraz the missing Xcode plugin manager.

Categories
Blog

Generic sharedInstance iOS implementation

One very common pattern when implementing Objective C singleton objects is the sharedInstance method.

Because I was a bit tired of repeating this code in several of my classes I decided to implement a Xcode Code Snippet that can be reused everywhere.

+ (instancetype) sharedInstance {
    static id _sharedInstance = nil;
    static dispatch_once_t _onceToken;
    dispatch_once(&amp;_onceToken, ^{
        _sharedInstance = [[self alloc] init];
    });
    
    return _sharedInstance;
}

As you can see simple code that can be apply to any object.

Categories
Blog

Good Macros

Here is a good write up, from Mike Ash, about the preprocessor and the proper way of writing macros. And here is a good example of a better Assert macro.