Xcode UI Tests problems

The problem with Xcode UI Tests

A little background

Ah, yes, automated UI tests. You cannot consider yourself a good developer and not love them. Or at least do them. Have tried them? Know about them?

To me, they are a lot like urban legends. Everyone knows about them, but not so many people claim to have seen them in action. And even fewer have actually seen them in action. But why is that?

Naturally, most often it’s the case of “Ain’t nobody got time for dat!”. But beyond… why do they tend to be overlooked. My theory is that they are simply too frustrating and tedious. There’s a major effort in making them easy to write and reliable, but really? Are they?

Lets look at Appium, for instance. It was supposed to be this great new tool that makes testing a breeze. And cross-platform too! But in reality it is (in my opinion at least) fragile. It can be slow, you have to wait for updates after a major Xcode release, and it’s not exactly cross platform in the real world. It comes with so much pain and maintenance costs, that it is often impractical to use.

And what about Xcode UI Tests? It was a huge deal when it was announced several years ago at WWDC. I mean, even before, we had UIAutomation, but surely, Xcode UI Tests are better, right? And yes, they are, but to be fair, it wasn’t that difficult to be better than UIAutomation.

The problem with UI Tests

Don’t get the wrong idea, I love the prospect of UI Tests. It would be an ideal way to test applications. It’s not manual, it’s relatively fast and it’s (almost) black box. Also, it’s really fun watching the simulator or your test device come to life and start tapping on buttons on its own.

That being said, why did I say it would be an ideal way to test?
It’s just because it often proves unreliable. There are just too many variables. So many moving parts need to come together in order for a test to run and execute to completion. Moreover, if you really want a black box test, you will have to live with your application accessing remote and/or persistent data. And by doing that, you become exposed to network issues and inconsistent state between test runs.

Additionally, if you look at the tools themselves, they can also be a bit unreliable. Just like I wrote about Appium above, it would be unrealistic to expect it to just work. You have to fight it all the time. And unfortunately, after many long fights, you will be tempted to abandon your tests.

The problem with Xcode UI Tests

With the release of Xcode’s UI Tests, one would expect that things would get better. And not because everything Apple touches magically turns into gold as many people believe, but because only they have the power to break through all the sandboxing and private API barriers and make something good happen. But I still feel there’s plenty to be desired.

Limited API

A major problem with the new Xcode UI Tests is that the programming interface is quite limited. Also, the documentation is seriously lacking. Now this is really unlike Apple. Usually, you’d get an API reference and a programming guide. But with UI tests, we get close to nothing. It almost feels like it’s incomplete.

Basically, all Apple provides is the User Interface Testing and the XCTest reference. Even doing a web search for it, doesn’t yield as many results as expected. I wonder why that is. Do people not understand it and avoid writing about it? Or they just ignore it?

Unintuitive classes and methods

While writing UI tests, you are never working with the classes you are familiar with from development. It’s always a facade (or proxy) of the real thing. Whether it’s XCUIElement, XCUIApplication or XCUIElementQuery, you will never be able to use the methods you are used to.

Text fields, switches, labels and buttons… they all have the same interface – they are hiding behind XCUIElement.

One nice example of how primitive the interface is, would be typing text in a text field. You’d expect there would be a property for that. But there isn’t. You have to type the text yourself. At least you don’t have to do it one character at a time. However, you DO need to make sure the text field has a first responder status by tapping on it. If you fail to do so, you’d get an exception. Additionally, if you want to set the text, not just append, you need to clear any previous characters manually. For that, you need to find the code for the backspace button (“\u{8}”, you’re welcome) AND also calculate how many times to type it in order to clear the whole field.

So, to do something so trivial and basic as setting the text on a text field, you need to:
* Tap on the field to make it a first responder
* See how many characters it already has
* Type backspace just as many times
* Type the desired text

And even though it takes 3 minutes to write a utility function for that, it just shows how unrefined the API really is.

Poor asynchronous operations

Sure, being asynchronous is probably not the highest priority item on a UI testing framework’s agenda. But shouldn’t it at least be in the top 5? Lets face it, some tasks take longer than others. And in the app scene nowadays, a server-side component is almost a must-have. So it should come to no surprise that tests needs to wait sometimes.

To be honest, Xcode UI Tests do. In a way… Sort of… sometimes. It’s of course quite blurry, since the resources are lacking, but here’s what I understood:

Waiting to idle

Yes, Xcode UI Tests “wait”. As far as I understand, waiting “for the app to idle” means that it will detect that there are animations still performing and wait for them to complete. But after they all finish, and some element you need is still not there, (boom). Assertion failure. Oh, well!

Waiting for long running tasks

Xcode UI Tests will not wait for several seconds in case something changes (by default). I think that was the case with other testing platforms, but not Xcode UI Tests.

Waiting for expectations

That being said, Xcode UI Tests support some sort of asynchronous tasks using expectations. And by “some sort of”, I mean that most cases are possible to achieve but sometimes quite annoying to implement. Spoiler alert – waiting for element to disappear or waiting an explicit time interval.

The basic idea is to create an “Expectation” with a predicate (most often the predicate is that an element exist, or a table has more than 0 cells). Then you wait until those expectations are fulfilled with a given timeout. If the predicate doesn’t evaluate to true after the timeout expires… bad news. There’s also a completion handler that gets called after the timeout but the annoying part is that there is nothing you can do there to avoid the test failure.

Most of the time, an expectation would look like this (in Swift 2):

_ = self.expectationForPredicate(NSPredicate(format: predicate), evaluatedWithObject: uiElement, handler: nil)
self.waitForExpectationsWithTimeout(timeout) { (error:NSError?) in
  if error != nil {
    print("*** Failed expectation for test: \(message)")
  }
}

For now, expectations don’t look too bad. The problems emerges when you realize how often you have to write that same code. As I said, every operation that might take a non-trivial amount of time, needs to have that. Normally, pushing or presenting a new screen wouldn’t require it. But then again, sometimes it does. At some point you stop caring and put it there as well.

On that note, what really gets on my nerves is that this is hardly explained in the documentation. Even more, using the famous recording mode, such code will never be generated. It will only generate taps making you assume you don’t need the expectations. Then you start running your tests only to find they often fail. I wonder how many people got too frustrated at that point and gave up.

Waiting specific time interval

As hinted above, this is something that’s especially frustrated about Xcode UI Tests. I don’t think it’s an edge case that developers might want to wait an explicit amount of time and then proceed. Even in UIAutomation, you could achieve that using action timeouts:

UIATarget.localTarget().pushTimeout(15);
UIATarget.localTarget().popTimeout();

It’s not ideal, because that’s just the time UIAutomation waits between actions, but still, it worked. However, Xcode UI Tests don’t have that…
If you want to wait explicitly, you have two options (at least I know two ways).

One would be a good old “sleep” on the thread. But lets face it – the intersection between programmers that “sleep” ( :) ) and programmers that automate tests, is not that big.

NSThread.sleepForTimeInterval(15)

Alternatively, some GCD magic can be employed. It’s a bit messy, though. But it’s a cool hack you can use to brag about when you meet your nerd friends:

func checkFor(predicate pred:NSPredicate, onElement:XCUIElement, afterDelay:NSTimeInterval, timeout:NSTimeInterval = 3) -> Bool {
  let waitExpectation = expectationWithDescription("Delaying for predicate \(pred) on element \(onElement)")
  let waitTime = dispatch_time(DISPATCH_TIME_NOW, Int64(UInt64(afterDelay) * NSEC_PER_SEC))
  dispatch_after(waitTime, dispatch_get_main_queue()) {
    waitExpectation.fulfill()
  }
  self.waitForExpectationsWithTimeout(afterDelay + 0.2, handler: nil)
  return pred.evaluateWithObject(onElement)
}

That’s not the easiest code to understand so lets explain it a little bit. We make an expectation and start waiting for it because we need to block the process for a while. And the trick is to automatically fulfill that expectation just before it “expires”. So we use grand central dispatch to fulfill the expectation after the timeout we want to wait. At that point, the process resumes because there is no expectation to wait for anymore. Finally, on the last line we evaluate the predicate directly, knowing the timeout has already passed.

Note: Another limitation about expectations is that there can only be one at the same time. That means you cannot wait for several things at the same time.

In general

I complained a lot in this article but I still want to end on a positive note. I actually like Xcode’s UI Tests, and I do use them. I’m convinced that they have a lot of potential. But on the other hand, they still need a lot of work until they become easy to use and reliable. it is all too easy to hit a brick wall with them and quit. After you go over the initial hurdle, it gets easier and you start seeing more and more potential with them.

I’m planning on writing a complete guide on using Xcode UI Tests in order to share my findings and hopefully spare some people a lot of hair pulling. But until then, only this rant about them will be available. Stay tuned!

Proxy design pattern in iOS

My thoughts on the proxy design pattern in iOS

What this article is all about

I might have to disappoint you, but this is not going to be tutorial on using the proxy design pattern. It’s going to be more like a discussion about how it is used internally in the Cocoa framework and how we can take that as example and consider that advice (or not) in our projects. So if you are just interested in what a Proxy is and how it’s used… Honestly, I have no idea what you are doing here. Just read the Wikipedia page or something šŸ˜›

The proxy design pattern

Just so we are on the same page on this, lets look at the definition for the proxy design pattern:

A proxy, in its most general form, is a class functioning as an interface to something else.

This is taken right from that Wikipedia page I mentioned. Reading it, though, gives a very vague definition of the proxy design pattern. A person with a wilder imagination would say many things in programming are proxies. Hmm, and maybe he’d be right.

Anyway, I like to think of a proxy as a “wrapper” that keeps the iterface from the orginal class. Naturally, who am I to say what a proxy is, and what not. I’m sure there are at least 5 counterexamples that prove my definition is incorrect. It’s overly simplistic, but I think it’s good to start with.

Mentioning wrappers… are they actually a design pattern? Turns out… they are! Check it out in Wikipedia! Ok, yeah, it’s just an alias for the Adapter design pattern, but it’s something!

I hate seeing memes in blog articles, so feel free to open it externally

The problem with proxies

I have a problem with the second part of my definition:

A proxy is like a wrapper that keeps the interface from the original class

— Me, one paragraph above

For simple classes, or more specifically classes with simple and short interfaces, that’s fine. If you look at the example given in the Wiki article, the public interface for the class is only one method. It’s extremely easy to mimic the same interface in the proxy. But what if we wanted to proxy a class that is way more complex. For instance UIView. We would have to copy every public method from UIView. That’s quite a lot. And it’s fragile – new methods can appear with every SDK release. And most of those copied methods would probably do the same thing – just call the real functionality. And I don’t think this example is exaggerated in any way. After all, It could be often useful to proxy a large object.

One possible solution would be to extract the interface as a protocol and have the original class and the proxy conform to it. But, really, that doesn’t make it better. The thing about protocols is, you still need to provide implementations for those methods. Again, there is a lot of copying going on.

Note I know protocols have default implementation in Swift 3, and that’s really cool, but that doesn’t really solve the problem.

It seems at this point we have hit a rock and we start to understand why proxies are not so common in our coding life. Or have we?

UIAppearance

The story about proxies ended for me for quite a while. I couldn’t find a solution to the problem of the common interface. It was recently that I remembered it while working on my previous article about app branding. If you check the documentation for UIAppearance, it says:

Use the UIAppearance protocol to get the appearance proxy for a class.

right from the start. Well, what do you know – here’s a prime example of the proxy design pattern. Moreover, UIAppearance proxies large, complex objects like UILabel and UIView. Basically most UI classes. So not ony does it mimic the interface of a complex class, but even several of those. Now this is worth some additional investigation.

What kind of object is UIAppearance?

The experiment

We cannot just open UIAppearance’s source code, but at least we can look at it’s declaration. I found the first instance of UIAppearance in my code and clicked on “Jump to definition”:

    public protocol UIAppearance : NSObjectProtocol {

    /* To customize the appearance of all instances of a class, send the relevant appearance modification messages to the appearance proxy for the class. For example, to modify the bar tint color for all UINavigationBar instances:
        [[UINavigationBar appearance] setBarTintColor:myColor];

        Note for iOS7: On iOS7 the tintColor property has moved to UIView, and now has special inherited behavior described in UIView.h.
        This inherited behavior can conflict with the appearance proxy, and therefore tintColor is now disallowed with the appearance proxy.
      */
    public static func appearance() -> Self

Hm, so it is actually a protocol. That’s something, but doesn’t really tell us a lot about who and how implements it. But what is that at the end of the snippet?

public static func appearance() -> Self

That can lead to somwhere. If you ever worked with UIAppearance, you know you typically call it using:

UILabel.appearance().<set something>

In this example, of course UILabel is only one of many classes that support UIAppearance. And if you go to UILabel’s header, you’d find that it conforms to the UIAppearance protocol. Interesting! So if you call UILabel.appearance()… you get a UILabel instance back. Indeed, the line let labelAppearance:UILabel = UILabel.appearance() compiles fine and in runtime, we can inspect that labelAppearance is really an object of type UILabel. Additionally, it is always the same object.

Well that’s a little disappointing. Does it mean that UILabel has a static label variable that holds all the appearance information and all set properties there are also reflected on new instances when they are created?

Next experiment – if UILabel.appearance() is a label itself, can we actually put it on screen and see what gets displayed:

    override func viewDidLoad() {
        super.viewDidLoad()
        // Do any additional setup after loading the view, typically from a nib.
        let labelAppearance = UILabel.appearance()
        labelAppearance.frame = CGRect(x: 20, y: 50, width: 100, height: 40)
        self.view.addSubview(labelAppearance)
    }

Easily enough, the code compiles and runs. But then:

*** Terminating app due to uncaught exception 'NSInvalidArgumentException', reason: '-[NSMethodSignature getArgumentTypeAtIndex:]: index (2) out of bounds [0, 1]'
*** First throw call stack:
(
    0   CoreFoundation                      0x000000011290e34b __exceptionPreprocess + 171
    1   libobjc.A.dylib                     0x000000010fc7e21e objc_exception_throw + 48
    2   CoreFoundation                      0x00000001128cbd5c -[NSMethodSignature getArgumentTypeAtIndex:] + 204
    3   UIKit                               0x0000000110ab14af +[NSObject(UIAppearanceAdditions) _installAppearanceSwizzlesForSetter:] + 293
    4   UIKit                               0x0000000110ab517f -[_UIAppearance _beginListeningForAppearanceEventsForSetter:] + 248
    5   UIKit                               0x0000000110ab53f9 -[_UIAppearance _handleSetterInvocation:] + 188
    6   CoreFoundation                      0x0000000112893a2e ___forwarding___ + 526
    7   CoreFoundation                      0x0000000112893798 _CF_forwarding_prep_0 + 120
    8   UIKit                               0x00000001103b0d75 -[UIView(Internal) _addSubview:positioned:relativeTo:] + 584
    ...

I guess the theory about UILabel.appearance() really being a label is slowly fading away. But that doesn’t make the reality any less disappointing. Lets look at the stack trace.

First of all, the exception description looks like a standard array index out of bounds assertion. Already, it seems UIAppearance just keeps an array of applied styles. But how?

Continuing on, we can start looking at the method calls. On 8th place, we see a call to addSubview. This is no surprise since the documentation specifically says that UIAppearance styles are applied when a view is added to a window. Next, 3 to 5, seems interesting. Invocation… Swizzles…?

Invocations probably refer to NSInvocation, a class encapsulating method calls. It’s a bit obscure, but if you’ve had to save methods along with parameters for later calls in (lets say) a dictionary, you might have had to use NSInvocation.

Swizzling, on the other hand, is something many of us know from the Objective-C runtime. Swizzling refers to the process of replacing a class’s method implementation with another one, effectively changing the class in runtime.

The results

At this point, we can make a pretty good guess as to how UIAppearance does its magic. It collects styling calls as NSInvocation objects in an array. Then, it uses method swizzling to override setters and apply those invocations to all new instances of the styled class. To make the compiler happy, especially in Swift, the appearance method from the UIAppearance protocol makes sure to return an object of the same class. That way all the class’ methods are accessible and statements such as:

UINavigationBar.appearance().barTintColor = themeColor

become possible. But in reality the underlying object is not an instance of that class, but a proxy collecting invocations, ready to apply them to any subsequent instances.

Next steps

We didn’t need to get too deep into Cocoa in order to understand how UIAppearance was implemented. Just some fiddling with its declaration and lldb was enough. Of course, for a lot of things we had to use our imagination and make assumptions. For instance, we inferred implementation details based on method names and undeterministic behavior.

However, a more powerful investigation method that works especially good in Objective-C, is looking at the class dumps. As you probably know, Objective-C is relatively easy to decompile. So there are tools available that will generate the source code based on compiled binaries. Moreover, for built-in libraries, dumps are readily available in Github. So before those libraries and frameworks get re-written in Swift, we can take advantage.

If you want to confirm our findings about UIAppearance or you still have questions regarding its implementation, a good place to start would be UIKit’s source code, and UIAppearanceProxy specifically, that you can find here

Thanks to Shoumikhin for suggesting that in the comment section!

Takeaways

The key takeaway for me here is that there is no clean easy solution to the problem at hand. When you proxy a class, it is your responsibility to carry the interface over to the proxy. And if that interface is non-trivial, the practicality of this approach starts to fade away. And while the proxy design pattern in iOS is definitely possible and also somewhat endorced by the Cocoa framework, it is not a simple and elegant implementation. It heavily relies on Objective-C and its ability to “shapeshift” at runtime.

So whether or not you would use it, heavily depends on how comfortable and open to the Objective-C runtime you are. I, personally, avoid it in my code and I get really suspecious about third party frameworks using it without a really good reason.

App Branding

App branding and UIAppearance

Introduction

Supporting several application variations sharing the same code base is a programming topic that affects lots of developers. Especially when you think back several years ago with the explosion of holiday themed games, lite and premium version apps and re-skinning. Not that companies have stopped doing those things, but it seems, at least to me, that it’s no longer that prominent.

But it’s not only that. We also have white label solutions and enterprise apps specifically tailored for a company. The point is that there are lots of uses cases for apps that need to change at build time according to external requirements, and share 99% of their code at the same time.

The problem with programming though, is that 99% still means you have to support two distinct configurations. Also, what starts off as 99% similar tends to slowly diverge to 95, then 90 and then even less.

There are a lot of ways to tackle this app branding problem. And I don’t think anyone is in a position to say which way is the correct or the best one. It all depends on the specific circumstances of the project at hand. It’s all about enticipating the scope of the version differences and in what direction requirements might shift in the future.

However, even with that in mind, there are certain best practices and platform fatures we can leverage to have a more successful branding implementation.

Techniques

We are going to go over several techniques that can be used to achieve app branding. They are all not perfect, but can be useful tools in the right circumstances. These are:

  • Branching
  • Build Targets
  • Subclassing
  • Configurations
  • UIAppearance

Often times several of those items will have to work together, in order to get the job done. Especially build targets are paramount to most solutions. By themselves, they are rarely enough, but coupled with others, they are probably the most powerful tool for app branding.

Branching

In a source controlled environment, you might be tempted to create a different branch for every branded version of your application. Especially if the new version requires a lot of changes, it might be easier to move to a new branch and implement changes without worrying too much about the main project – you cannot break your generic app if you’re working in a different branch. However, the price for this decision is quite big. With time your branches will diverge a lot. And even if they didn’t, keeping them in sync as new features and fixes get added, would be tedious and error-prone.

Another similar idea would be to extract the common code into a framework, submodule or whatever is convenient for the prticular case, and then have different projects, using those components and implementing the different, “brand-specific” parts. This might seem like a nice idea, and if done correctly might be genuinly awesome, but it is, in my opinion, difficult to achieve. For one thing, the distinction between “common” and “brand-specific” is too vague. There is rarely a single inflex point where you can draw the line. So often, you will have either too little “common” code and end up duplicating features in the “brand-specific” section, or the opposite – you will have too much specifics in you “common” code, leaving you desperate to find ways to change that behavior depending on a version.

So unless you have a really good idea of how you might separate the code and how new requirement might affect that idea, I think you should treat this approach with a lot of suspicions.

Build Targets

This is Xcode specific, but every IDE should have a way to achieve something similar. As you probably know, an Xcode project can have several targets. The ones you usually see, are targets for the application, for unit tests and for UI Tests. But of course, you can add your own. Each target has different build settings and can work with a different subset of source files. What makes targets perfect for app branding is the fact that you can use different info.plists in order to have different images, bundle IDs etc, different source files (you can choose which source file is included in which targets), different artwork, different Interface builder files etc.

This makes it really easy to have different resources for your different app variations. You can even have files with the same name, but included in different targets. In fact, this is a common solution to branding problems. On the other hand, managing which item goes to which target is a bit error-prone. Especially after a while, when app branding is not something you actively think about during feature implementation, it is easy to make a mistake which is going to lead to obscure build error or even worse, crashes and bugs.

So, even though targets are a powerful tool, they have their caveats so you should take special care while using them.

There’s still a lot to discuss about build targets, however most will come up while discussing the next app branding techniques. So lets continue…

Subclassing

The idea behind subclassing is simple. You create a generic (maybe even abstract) class that implmenets an interface for a particular feature. Then, you create a subclass for every app variation you need. This subclass actually implements the functionality necessary for that variation. Of course, then you need to make sure the right subclass is used. It might be some sort of factory method, or what we just duscussed – targets.

At first, subclassing seems like a perfect option. In fact, that’s why object-oriented languages have subclassing – to extend a base implementation. But upon closer examination, you often see that this is not true. To the contrary – you are going against OOP principals. Especially Liskov’s substitution principle. Extending the class quickly turns into slaughtering the base implementation and constantly trying to do something completely different in the subclasses. At some point every class in the hierarchy is so different that the only reason for them to co-exist is because they should get called at the same locations in code. And that’s where it gets ugly.

At least that’s my experience. Maybe I’m doing something wrong, but up until now I’ve failed to see a well working app branding solution that uses subclassing extensively.

That being said, subclassing is sometimes unavoidable. And it can generally be ok as long as it’s kept to a minimum.

Another variation to the subclassing technique (that I like better) is using classes with the same name, but in different targets. This is now especially easy in Swift since you most often don’t need import statements. What I like about this variation is that it completely ditches the idea of inheritance. It acknowledges the fact that those classes are not really similar so you don’t have to constantly fight against inheriting some base functionality. It’s just 2 (or more) classes with completely different implementation, that happen to have the same name.

Configurations

Configurations are not like the previous techniques we discussed. In fact, they often rely on subclassing and build targets for their functioning. The basic idea is to hold constants that toggle functionality and hold values for properties, specific to an app variation. But that implies having different configurations for each variation. And to differerentiate between them, of course you need something like targets and/or subclassing.

On the implementation level, a “configuration” can be, for instance, a XML, JSON, plist file (essentally a resource file) or a source file full or constants (in Swift probably a file full of structures and enums). Then, the easiest way would be to have the different files only in their respective target.

UIAppearance

Now we are getting to the good stuff. And also the bad stuff. Definitely the interesting stuff.

For a general overview of what UIAppearance does, check out the UIAppearance reference page. But in short, UIAppearance is a protocol that allows you to change the default values lots of the UI classes in UIKit use to visualize themselfs. The way that works is that you, for instance, specify that the text color for UILabels is green. And from then on, every UILabel instance that is created, gets that green color by default. Pretty neat!

Note: UIAppearance sets the default value, but if the same property is changed after that, the value gets overriden. And while this rule makes total sense, it is sometimes annoying and creates subtile bugs. For instance, if you set the text color of a label in Interface Builder, the UIAppearance value is overriden because Interface builder applies its changes after the styling from UIAppearance is done. You need to make sure to leave the default option in Interface Builder.

UIAppearance is really nice for applying application-wide values. Much like setting the tintColor value in your root view, but much more flexible and complicated. And that’s what makes it great for branding. Especially if you what to change your app’s theme color, UIAppearance is a great option.

The good

Think about it – if you had to change a color or something similar in your whole application, it would be a nightmare. Tracking down every view that uses it, always mssing some cases. With UIAppearance, you only need to set that color once, and then it will apply for every instance of that particular class after that. Something as simple as this:

UILabel.appearance().textColor = themeColor

You can even go one step further and extract those values in a resources file – a plist for instance. Then, as your application is loaded, you can read that file and apply the styling. That could be really nice, although I don’t think a situation where you can give that resource to your non-tech colleagues and have them change it themselves, is realistic. I just think that at least a minimal tech background is needed to grasp the concept of what works and what doesn’t.

The bad

UIAppearance is no doubt a great idea. But it’s not for the short tempered, at least not in the beginning. There’s just a lot of subtleties around it. As I mentioned, UIAppearance properties get applied to all new instances of the particular class. But anything that works on those same properties after that, will override the UIAppearance values. And while this is definitely the right behavior, it is not always what you want to happen. This often leads to obscure bugs. So at the start, you will find yourself juggling between UIAppearance, Interface builder and code to figure out why something is not properly applied.

Another common issue you will encounter, is applying a rule too liberally. Sometimes you think a property is universal and should be applied everywhere, but in reality in turns out there are exceptions. Your first instinct might be to override that value after UIAppearances are applied, but that’s also not ideal. It’s just too implicit and hard to maintain. Luckily, this is a place where subclassing can help!

Subclassing and UIAppearance

I previously “preached” using subclassing with caution, and yet here we have a whole section dedicated to that. What makes UIAppearance different?

Truth be told, my previous statement still holds – you should still avoid subclassing whenever possible. However, it can still be quite helpful when using UIAppearance. Lets return to the small example above:

UILabel.appearance().textColor = themeColor

It seems harmless, but I would argue that UILabel is often a terrible candidate for UIAppearance. Even if you want to apply an overall theme to your application, there are usually labels that should have a different style. Sometimes, elements around those labels need to be branded, but the text should remain the same. For instance, you might want to brand a navigtion bar in red, but the custom navigation title inside should be white for contrast.

This poses a question. How do you handle UI elements that don’t have a single style, but several?

Since UIAppearance uses classes to differentiate between elements, a possible solution would be to make those elements instances of different classes. Getting back to the example, it would change to something like this:

BrandedLabel.appearance().textColor = themeColor

BrandedLabel would be an UILabel subclass that is actually quite empty. It needs to behave exactly as a normal label, but it… kind of need to be not UILabel. After that, you only need to make sure all labels that need to change are BrandedLabel instances.

It’s not super clean, but gets the job done with not a lot of added complexity. Empty subclasses are not a really nice architecture, and I’m sure they violate some OOP principles. However, they hardly make the code harder to read, especially after you understand their purpose and learn to ignore them.

Conclusion

App Branding is an inherently difficult problem to solve. There’s no perfect solution and it’s almost always a pain. I cannot claim that the techniques we discussed here are the right one. Definitely they are not an exhaustive list of solutions.

They are just a collection of items I found to be useful and have helped me a lot on the past. At the end of the day, every project is different and calls for different strategies. So you will have to do a bit of experimenting. Good luck!

DevMonologue Magazine in iBooks

I hope you guys enjoyed Issue 01 (Going Open Source) of DevMonologue Magazine.

I know it was a little awkward to download a PDF from Github, so I’ve decided to upload a version on the iBooks store! Check it out
iBooks Store link for DevMonologue Magazine

Of course, it is completely free, so it will hopefully be more convenient for you guys to download, sync between devices and read.

An image showing the cover of the magazine