Friday, November 22, 2013

UIColor - why hast though forsaken me!?


[UIColor colorWithRed:0.15294117647059
                green:0.16470588235294
                 blue:0.84705882352941
                alpha:1.0];

So I start this article with a snippet of code. A very common snippet in fact. It's simply some Objective-C that creates a UIColor object with red, green, blue and alpha components. Now, aside from the alpha value, how easy is it to read this code? How easy is it for a designer to relay color in this float form to developers? In fact, when has a designer ever, in the history of iOS and Mac OS X development, provided the color for use in an app as float values? I don't think there's a number closer to 0 than that. And last, how easy is it for a developer to look at this code and understand what color is being created here? So in this post, I'm going to take a very short amount of time making everyones color coding lives easier with some UIColor code extensions.

As easy as RGB...A


Now looking at the above code snippet, all I can think is, "there has to be a better way!" And, of course, there is. The easiest way to improve on the float based construction of a color is to think of how we describe color in a digital world. Well, 99 times out of a hundred, we describe color (in computers) by their red, green and blue components - or better known as RGB. Now of course, the UIColor describes the RGB components, but each component is treated a float. However more simply, when I speak with designers, they describe colors using a 16 million color palette, or more specifically with the values of each component being between 0 and 255. Let's look at what the code would have looked like if Apple had used 0-255 as the RGB component value inputs instead:
[UIColor colorWithRed:39
                green:42
                 blue:216
                alpha:255];

Wow! It's like a whole new world! Not only can you easily gauge how much of each color component is being used, you can actually remember the values and, more importantly, verbally relay them between designer and engineer! Well, Apple did not provide us with this API, so many developers take up the practice of converting the value in their code:
[UIColor colorWithRed:39.0f/255.0f
                green:42.0f/255.0f
                 blue:216.0f/255.0f
                alpha:255.0f/255.0f];

This totally works, but it took more than 90 characters of code to describe it! That's unreasonable, I'm a programmer and inherently hate verbosity (at least in code). So let's take this a step further and use a handy dandy C macro to make this MUCH more compact.
// Declare macro
#define COLOR_INTS(r, g, b, a) \
[UIColor colorWithRed:(r##.0f/255.0f)   \
                green:(g##.0f/255.0f)   \
                 blue:(b##.0f/255.0f)   \
                alpha:(a##.0f/255.0f)];

// Call macro
COLOR_INTS(39, 42, 216, 255);

Creating a UIColor is now merely 29 characters of code (excluding the macro declaration of course)! This is wizard and much better. In fact, for most this is as much as would ever be needed! However, let's take colors a step further. What if I wanted to describe a color as a single value and not 3 color components and an alpha component? Well, as it turns out, colors fit beautifully into computers because we can describe them in binary - 32 bits in fact. Now each color component is between 0 and 255, which is 256 values. Well that just happens to perfectly fit into 8 bits! And, as we all know, 8 bits is a byte. So if each component is a byte, we have 4 bytes and therefore 32-bits. What else is 32 bits? An unsigned long!
Well, as it happens, colors don't "magically" happen to fit into 32-bits - it's actually that computers evolved over time to support more and more bits to describe their pixels on screen. The first bitmap capable computers were the IBM PC family of computers that could support monochrome bitmaps, that's 1-bit color - literally on or off. The first colors in computers were with 2.5 bit color that was pretty hokey. It's really 3 bits of color, but only 2 bits indicate colors and the last bit changed the intensity of the color on the screen and was called CGA. Next in line was EGA, 4-bits of color glory giving 16 different colors to show on screen at the same time. Computers progressed to 8-bit monochrome providing 256 different shades of grey (eat your heart out E.L. James). But those 8 bits could also provide, for the first time, actual ranges of color! 8-bit color was 3 bits red, 3 bits green and 2 bits blue providing computers with color in a single byte of data. They chose blue as the deficient color because they wanted the colors to fit into 8 bits and since the human eye has half as many blue color receptors as red and green it made sense to cripple the color we are least able to see. This color standard was called VGA. Well, if you like 8-bit color you'll love 16-bit color! That's 4 bits for each color plus the addition of an entirely new channel...alpha! Alpha is the component of a pixel that indicates how transparent it is; the higher the value, the less you can see through it. And, alas, 32-bit "true" color was born with a full byte for each component, which is perfect for 32-bit processor computers. Now colors have progressed further all the way to 64-bit color and beyond, however the ability to even visually see more than 16 million colors is so minute that 32-bits color has become the defacto bit depth for most screens you see today. Well, that was a fun tangent! Back to our post!

So given that we can represent color in 32 bits, it has become common practice to express those bits in Hex. So the color we've been dealing with would actually be the same as 0x272AD8FF, also known as RGBA. Alternatively, we can state the color as ARGB: 0xFF272AD8. In fact, this is the most common way I've ever used to communicate colors with designers. So if the language we communicate colors with is Hex, we should be able to extend UIColor with a simple category to accomplish just this. Let's first look at the interface we want to create:


typedef uint32_t UIColorARGB;
typedef uint32_t UIColorRGB;

@interface UIColor (Extensions)

+ (UIColor*) colorWithRGBString:(NSString*)hexString;

+ (UIColor*) colorWithARGB:(UIColorARGB)color32Bits;
+ (UIColor*) colorWithRGB:(UIColorRGB)color32Bit;

- (UIColorARGB) argbValue;
- (UIColorRGB) rgbValue;
- (NSString*) rgbStringValue;

@end

So with our category we want to accomplish 3 things. 1) We want to be able to create a UIColor with hex - which fortunately can easily be expressed in Objective-C. 2) We want to be able to create a UIColor using an NSString. 3) We want to do the reverse of 1 and 2, thereby being able to retrieve a 32-bit representation of the color as well as the NSString representation.

// Create with ARGB value
[UIColor colorWithARGB:0xFF272AD8];

// Create with RGB value
[UIColor colorWithRGB:0x272AD8];

// Create with String
[UIColor colorWithRGBString:@"0xFF272AD8"];
// or
[UIColor colorWithRGBString:@"#FF272AD8"];
// or
[UIColor colorWithRGBString:@"FF272AD8"];
// or any of the above 3 without the alpha
[UIColor colorWithRGBString:@"#272AD8"];

Now isn't that so much easier than using colorWithRed:green:blue:alpha? The answer is, Yes, yes it is! Normally I'd go into implementation details on how to implement these methods, but they are honestly so straightforward now that we know how to describe color that I'll just leave it as an exercise. That plus I wrote this while waiting for my delayed flight home and am exhausted. I won't leave you completely hanging though, as usual, my github repo has everything implemented.

Sunday, October 27, 2013

Easy UITableView optimizations

Now this may be the most simplistic blog post I write, but I think it's something that every iOS developer should utilize.  UITableView is an incredibly fundamental view in iOS and is used in many many apps.  However, I can't help but notice over and over so many amazing apps out there that use table views but have the jarring effect of not loading the data for the table view's cells' content until the cells are visible.  I want to take this blog entry to address 3 missing pieces for improved table view experience: 1) loading NSURLConnection data while UITableViews scroll, 2) buffering UITableViews so the content loads before it is shown on screen and 3) rendering a network graphic on a background thread so that the UITableView doesn't stutter (with a blocked main thread) when the network graphic is decompressed and rendered.

Smooth Tables Views is easy as 1, 2, 3...

Sunday, August 25, 2013

Anatomy of a Singleton

So why would I want to cover such a fundamental concept as how to create a singleton?  Well there are two reasons.  First, it is actually surprising how few developers I come across that know how to make an effective singleton object - so perhaps the concept, though fundamental, is not nearly so basic.  Second, as with many patterns in programming, there are many ways to accomplish the same task, and that can be fun to examine.  Let's step through the ways we can implement a singleton in Objective-C, some of which are applicable in concept to other languages too.

Lots of ways to skin a cat...er...singleton

Tuesday, August 13, 2013

HTTP Live Streaming - Videos On Demand (HLS - VOD)

HTTP Live Stream also known as HLS is cool.  Really cool.  The concept if fairly simple, people have numerous different network speeds and those speeds can change over time as well - so how do we deliver the user the best quality streaming media in the fastest way possible?  The short answer is take your media and encode it to numerous different outputs that range in bitrate so that you can dynamically select which source to be shown at any given time.    Now the specification for the protocol can be daunting and the vast configuration possibilities can be overwhelming, but truly, the simplicity of creating a video on demand that supports HLS is quite easy - and all platforms support it.  In this article I will go step by step through the process of how to take a source video and then output it into the numerous bitrate videos we wish to use and I will then convert those videos into HLS compliant streams and stitch them together.  I'll finish with a link to my github repo that has an open source Mac OS X project for converting 1 source video into a variable bitrate HLS stream, which can easily be hosted (I use an S3 bucket) and immediately start providing dynamic video content to your users.  See Apple's documentation of the technology for more thorough explanation and detail of how to use the protocol.

Anatomy of an HTTP Live Stream

Tuesday, July 9, 2013

Updating UITableView with a dynamic data source

UITableView is one of the most versatile UIViews in UIKit.  It can be used in so many ways, the mind boggles.  And it's greatest benefit is efficiently showing data (as cells) with low overhead.  It not only can restrict generating UI to only the cells that are shown in an efficient manner, it can also update its UI with animations in a very efficient manner using deleteSections:withRowAnimation:, reloadSections:withRowAnimation:, insertSections:withRowAnimation:, moveSection:toSection:, deleteRowsAtIndexPaths:withRowAnimation:, reloadRowsAtIndexPaths:withRowAnimation:, insertRowsAtIndexPaths:withRowAnimation:, and moveRowAtIndexPath:toIndexPath:.  But what if the management of the data source that backs the table view isn't maintained by your application?  What if you have a REST API that returns a JSON data structure that you use to populate your UITableView?  If that data ever changes on a subsequent GET, you have little choice but to perform a reloadData, right?  No way!  We're PROgrammers! We can tackle this!

Dynamically updating a UITableView


Friday, June 14, 2013

Logging: The Most Important Part of Any Application

Bold statement, right? But after over a decade of production development work, whether it's a brand new project, coming into a pre-existing project to clean up or just a prototype; the first and most important task I take on is having a robust logging mechanism. 2nd is ensure there is a robust crash handling mechanism in place - which I should touch on some other time - but first and foremost is logging.

Logs! Logs! My kingdom for some logs!


First, lets take a moment to really ask ourselves what we need from "logging".
  1. Logs must be fast and not interfere with application execution
  2. Logs should be filterable by their importance
  3. Logs must be easy to write
  4. Logs must be accurately timestamped
  5. Logs must be persisted on disk
  6. Logs must be retrievable
  7. Logs must not adversely affect users (like disk bloat)
  8. Logs should be visible as they occur (in the console)

Now this list may seem like overkill, after all it's just logging right? But I adamantly believe that not having any one of these items taken care of from the start will only lead to slowed productivity in the development lifecycle of any application. Now, nicely enough, iOS and Mac OS X have built in logging to the console with NSLog that should easily take care of all of our needs, right? First, I want to say I love NSLog, nothing is easier for just getting output right away in an application without any fuss. But sadly, NSLog just doesn't meet the requirements leaving it to us as developers to create our own solutions (which I will share my lightweight, go-to, re-useable logging solution at the end). Well if NSLog is out, let's tackle the requirements one at a time and establish what we need and why we need it.

Thursday, February 28, 2013

View Unloading into the Future!

When Apple released iOS 6, they stated that developers were having "trouble" with properly using viewDidUnload and viewWillUnload and decided that ultimately the memory hit from releasing objects in these methods wasn't enough of a concern to keep those methods and they were deprecated.  It was basically a nice way of saying that a lot of developers are so terrible at view lifecycle management that they were just going to remove the unload methods so that developers didn't continue to mess up their app by not knowing what they were doing.  Now I personally applaud Apple for taking into account this problem and dealing with it in a way that doesn't hurt legacy apps.  However, I do believe that all APIs are tools that when wielded appropriately can be useful for building something that works well.  So when viewDidUnload and viewWillUnload were deprecated, one of the first things I set out to do was port them so that I could continue to use these "tools" into the future.  Now, if you don't want to use viewDidUnload or viewWillUnload and want to conform to Apple's recommended application life cycle design guidelines then this article won't likely help you, and I must credit your wisdom.  For the rest of you, let's jump into memory warnings!

viewWillUnload and viewDidUnload ported to iOS 6


Wednesday, February 27, 2013

A Better NSData Description

NSData has not always returned the HEX string of its data.  There was a time when it behaved far more modestly (and usefully in my opinion) when it just indicated it's pointer and length.  Let's take advantage of the method swizzling tools we learned about in a previous post so that we can get NSData's description to be something more useful than a data dump - and we'll make it configurable too so that at runtime you can decide how NSData's description should behave.  I'll also throw in an optimal NSData-to-hex-string method for good measure, hopefully to help counteract the awful practice some developers have adopted of using the NSData description for that serialization.

Putting NSData's description on a diet!


Method Swizzling

Objective-C is an amazing language.  So many possibilities with dynamic runtime typing and built in polymorphism.  But one of my favorite features of mutable runtime objects is the ability to Method Swizzle, which is effectively the ability to add a method or exchange 2 methods.  The usefulness of method swizzling is vast, such as adding a method to an older SDK that the newer SDK has or perhaps changing the functionality of an existing method.  In this post, I'll just give a quick implementation for method swizzling that can be reused over and over. A word of warning though, method swizzling can be very dangerous as you are effectively modifying the way existing code that has already been vetted works. 9 times out of ten, you can solve a problem without modifying the runtime and using object oriented patterns. Only when you have no choice should you consider method swizzling - and even then, you probably shouldn't.

Swizzling Methods for the win!



Monday, February 25, 2013

Better Reference Counting (Safe Release)

When it comes to manually managing memory, it's absolutely fantastic to have coding patterns for making your memory management duties...well...manageable.  Reference counting is one such pattern that is widely used throughout computer programming.  COM (which is on top of C++) uses it extensively, and thus the underlying system of memory management in C# uses it, but so does Core Foundation (C level API on Mac OS X and iOS) and, even more noticeably, is that the Objective-C language has the reference counting memory management pattern built in.

At this point, I assume everyone knows what reference counting is and how to use it. If not, you should verse yourself with Apple's Memory Management Overview.  Now since Apple has introduced Automatic Reference Counting (ARC), objective-c memory management has reached near trivial levels as that of managed memory languages like Java and C#.  But for those of us that need to support older platforms, work in legacy code bases or develop public libraries that require non-ARC support, being elegant with reference counting is very important.  And even those of us that are converted over to ARC, we still need to be aware of Core Foundation memory management which does not have ARC.

So that was a serious introduction to nothing it would seem! Well, what this post will actually cover is the pitfall of recursive (aka reentrant) code that can lead to crashing in a ref counted world.   Basically, we'll deal with releasing an object that leads to it being released again.

The problem: reentrant releases!