mdominick.com

Dell’s Project Sputnik —

Been to a developer conference or meetup recently? If you have, you might have noticed something odd. A large portion of the attendees using Macs. Now if that conference was an iOS or OS X developer event, then it probably makes  a lot of sense, but what about web and backend developers? Is there are reason for all those Macs? Well, that’s a question that Dell has set out to answer with their Project Sputnik.

Sputnik is an initiative to design a custom spin of Ubuntu 12.04 LTS for the Dell XPS 13. If you don’t know the XPS 13 is one of Dell’s ultrabooks. Dell wants to address the web developer market that is so fond of Apple.

I am really excited about this. Ubuntu was at one time my dev OS of choice thanks to apt-get. Currently, dell is not offering a pre-configured machine with the 12.04 image, but you can download it here and they claim that if there is enough interest they may start offering XPS’s preconfigured with Ubuntu, so if you are interested in one of these machines or just a Linux fan, let them know.


Phonegap the Bad and the Ugly —

Times are tough and development budgets seem to be getting smaller and smaller, assuming that you are not Draw Something or Instagram. My experience has been that clients who are interested in supporting both Android and iOS do not generally want to develop two native applications. The reasons are obvious: cost and time.  So the conversation tends to turn to cross platform solutions. Currently, there are two types of cross platform mobile solutions for non-games: web based ones and Mono. I am currently doing a little work in Mono for Android and will write about that at a later date.

The most obvious web based solution is probably Phonegap. Phonegap has been around for a while and allows developers who have HTML/CSS/JS skills to leverage those to develop rich cross platform mobile apps. That’s all true. However, there are a few issues with Phonegap: it is not a mature platform, is a huge dependency, and is nowhere near as performant as native code.

This will probably be the most inflammatory issue I have with Phonegap, but I stand by it. Phonegap is not mature and it shows. A lot of the more complex and useful functionality comes from community plugins. However, the platform has to date been in such a state of flux, that you are likely to find that many plugins don’t work or at least don’t work without some form of modification on the most recent version of the platform. This may seem like a relatively small issue but if you look at it in terms of developer efficiency, then it becomes a bit more serious; do you want to be hunting down the right version of the right plugin for your version of Phonegap?

Dependencies are a necessary evil on any project and plugins are dependencies. Even if you are developing a native app you are taking a dependency on at least a language and one or more frameworks. Using a tool like Phonegap adds a big dependency on Phonegap itself which also depends on those native dependencies you were trying to avoid. Worse still, since the Phonegap must interact with Cocoa Touch or Android, there is a chance that you will have “mystery meat crashes” on one or both platforms. One example on iOS is that Phonegap does not do a great job with memory management, so your choices are use ARC (only recently an option), dropdown to Objective-C and write some “release” statements, or run the risk of seemingly random crashes in the wild.  Another issue with such a large dependency that depends on one or more distinct dependencies is that you end up with the lowest common denominator between all platforms. For example, there is no iCloud support in Phonegap nor is there Newsstand support. Someone could write a plugin for these but those would be yet another dependency in your app and any changes to Phonegap or worse Newstand or iCloud could break your plugin.

It is unlikely that you will be developing the next Infinity Blade, but performance still matters even outside of the games space. Phonegap is not as fast as a native app. It can’t be. Normally, this isn’t a huge issue for most apps but it is important to consider during the planning stages of your app especially if you want to use the camera or have a flashier UI; the camera is noticeably slower in Phonegap. As always, your app’s tolerance for the performance hit will depend a lot on the spec, but it is something to keep in mind.

Having said all that, there are cases in which Phonegap is a good choice. If budget is a huge issue, cross platform is a must on day one, the app will be pretty plain, and performance is not a chief requirement. As always, you need to pick the right tool for the right job, but remember there are no silver bullets. Questions? Comments? Rage? Find me on Twitter or Google+.


Warning: Google Drive and Git Don’t Play Nice —

When Google’s GDrive was finally made available to the public, I was thrilled to see that the pricing structure would allow me to get double the space for the same amount of money I was paying Dropbox. Reading the description, it seemed that GDrive had all of the features that I liked from Dropbox and even offered an equivalent to Dropbox’s add on packrat service.

In short, it seemed like a great deal. So I did a trial run. I moved (copied would be the more accurate term) some of my personal repos from my Dropbox folder to my shiny new Google Drive. The initial sync took a long time (a little over a day) but that is to be expected with any of those types of services.

My initial impressions were mostly positive. However, I did notice that GDrive’s Mac OS X app uses four times as much RAM as Dropbox’s. Still, things were going pretty well and RAM is cheap, so for the money I was saving on storage it was worth the extra memory.

My main use for Dropbox is hosting Git and Mercurial repos along with one or two SVN ones that I haven’t had time to switch over to Git. Things worked just like they did with Dropbox. Until my secondary machine synced with the GDrive. on that machine a git status showed that all the files had been removed from the repo. I readded them and things were fine until I moved back to the main machine where I saw the same issue.

I have done Googling and can’t seem to find a reason for this. The only discussion I have found of people using the GDrive in this manner seems to have ended with another user warning the Google groups asker that there could be potential issues.

Sorry to say that I don’t have a fix, but I am migrated back to Dropbox. It does seem that you get what you pay for. That might seem harsh to some of you, but if you do software development for a living that is the kind of issue that should not be tolerated at all. Let me know if you have had the same experience or not on Twitter or Google+.


Know Your Class: How to Determine an Object’s Class in Objective-C —

Programming in Objective-C is a pleasure. Its dynamic messaging systems allows us to do a lot of little messaging tricks that we could not do in other languages. However, when it comes down to it Objective-C code will crash if you send a message to an object that does not handle it, just as Java code will crash if you try to call a function from an object that doesn’t know how to deal with it. Thus, it is important to know what class you are dealing with, especially in certain strange situations.

For example:

- (void) longImageRequestFromS3 {
     ASINetworkQueue* q = [ASINetworkQueue alloc] init];
     [q setRequestDidFinishSelector:@selector(requestFinished:)];
     [q setQueueDidFinishSelector:@selector(qFinished:)];
     [q setDelegate:self];
     for (int i = 0; i < [imageURLS count]; i++) {
        ASIHTTPRequest* r = [[ASIHTTPRequets alloc] initWithURL:[imageURL objectAtIndex:i]];
        [r setTag:i];
        [q addOperation:r];
     }

     [q go];
}

- (void) requestFinished:(ASIHTTPRequest *)r {
    UIImage* image = [UIImage imageWithData:[r responseData]];
    [yourPrivateMutableArray replaceObjectAtIndex:[r tag] withObject:image];
}

- (void) qFinished:(ASINetworkQueue *)q {
    [yourTable reloadData];
}

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   /* norma tableView stuff */
  [yourMagicalCell setSomeImageViewsImage:[yourPrivateMutableArray objectAtIndex:[indexPath row]]];
  return yourMagicalCell;
}

That code sample is far from perfect and is designed to show a point. Let’s walk through it. If all goes well each cell’s someImageView will have an image from an array of images set, but what happens if the ASIHTTPRequest that gets the image fails. Let’s assume that there are a total of ten requests in the queue and only nine succeed. Guess what? Your app crashes. Why? Because you will have tried to use an ASIHTTPRequest as a UIImage, sending a number of message to an instance that cannot handle them.

So the problem is that we need a way to make sure that we are not trying to use an non UIImage as a UIImage. Your first instinct might be to try something like this:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
   /* norma tableView stuff */
   if ([[yourPrivateMutableArray objectAtIndex:[indexPath row]] isKindOfClass:[UIImage class]] {
     [yourMagicalCell setSomeImageViewsImage:[yourPrivateMutableArray objectAtIndex:[indexPath row]]];
   }
return yourMagicalCell;
}

Before the more picky of you mention it: yes, this sample applies to isMemberOfClass as well. I don’t know exactly what causes it (I have some theories that I will not float here) but at times that if check can actually pass even though the object will not be able to respond to UIImage’s messages and will crash your app.

However, there is a better way:

- (UITableViewCell *) tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
/* norma tableView stuff */
  if ([[yourPrivateMutableArray objectAtIndex:[indexPath row]] respondsToSelector:@selector(CGImage)] {
    [yourMagicalCell setSomeImageViewsImage:[yourPrivateMutableArray objectAtIndex:[indexPath row]]];
  }
return yourMagicalCell;
}

The difference here is that we are no longer checking the class of the object, but rather if it responds to a specific message (CGImage in this case). This is a less error prone way to solve the problem. On a more opinionated note, I like this way of looking at the problem a lot, since it takes advantage of Objective-C’s concept of messaging.

Hope this helps you, if you have any feedback I am on Twitter and Google+.


Review: Mastering Grails 101 —

I like Ruby and have a soft spot for Java and all things Java, since it was my favorite programming language before I started my professional career and the language that got me my first coding gig. So you’d think that I’d love Grails, a platform that aims to be the best of both worlds. You’d be wrong. However, O’reilly’s tutorial on Grails is pretty good. However, I am not sure that I would recommend it for anyone but a professional developer, as the presenters do seem to assume that the viewer has some professional (mostly Java) experience.

Like all O’reilly videos the production qualities were superb; the video and audio were both crystal clear and I had no problem viewing the code samples on screen. The presenters were very knowledgeable and took time to walk you through some of the more confusing aspects of Grails. The content was  introductory enough that most developers who have had a little Java  experience (in a professional environment of course) would be able to grasp most, if not all, of the concepts and examples laid out by the presenters.

Of course, nothing is perfect. The short length of the individual videos is downright annoying. Some of them are as shorts as three minutes long and you have to manually click to load up the next video in the web player. There is no reason for this. Oreilly of all organizations should be able to either cut multiple chapters into longer videos or enable autoplay on their player. Still, it is hard to fault the presenters for the presentations platform’s failings.

Overall, I would recommend this series to any Java developer that is thinking of taking a step or sto toward the Ruby on Rails side of life or to anyone who has heard of Grails and is curious as to what the hype is about. This series is not appropriate for students or hobbyists.


AppCode VS XCode —

I hate XCode but really want to love it. Most Cocoa developers have had more than a few bad experiences with XCode where it has crashed more than once in a day, magically, lost track of files, failed to warn you of naming conflicts in assets, or simply dead-locked your Mac; if you really want to watch XCode cry do a git checkout with a project open, that tends to bring things to a grinding halt, especially if there is a difference between the project files on each branch. This kind of thing becomes very frustrating as I am sure you are aware.

JetBrains has come to your rescue with their new AppCode. AppCode is an alternative IDE for Mac OS X and iOS development. It does a lot of things a lot better than XCode, but there are also some issues with it that prevent it from being a full replacement for XCode.

On the good side, AppCode offers much more advanced refactoring options than XCode, appears to be much more stable, has more intelligent code completion / suggestion. Like XCode, it allows you launch your App on your Mac, iOS device, or iOS simulator. It integrated with SVN, HG, and Git. I can’t speak to that features as I prefer to use source control  from the terminal; it is also significant that as of XCode 4, Apple has added some Git integration into their offering. Unlike XCode, AppCode has full support for plugins and can even use the full range of plugins from JetBrains’ other products, such as IntelliJ. My favorite feature, other than stability, is Vim emulation; yes, AppCode allows you to use Vim keyboard shortcuts while editing if you prefer to work that way.

Naturally, AppCode is not perfect. In fact the issues with are less bugs and more that the product feels incomplete in a number of significant was. It cannot work with nib (or xib if you prefer) files directly. That’s right if you click a nib in AppCode you’re popped back into XCode. This goes the same for storyboards and CoreData data models.

These limitations prevent AppCode for being a full replacement for XCode. However, AppCode is significantly better for actually writing code and if JetBrains was able to get some sort of integrated Interface Builder functionality and CoreData model editing functionality, then AppCode would be a true alternative to XCode and would be my full time IDE.

Thoughts? Questions or comments? Get in touch on Twitter or Google+.


GDrive Mac Performance Issues. —

I am always looking for ways to minimize costs and maximize the effectiveness that I get out of my tools, so it should be no surprise that when Google’s GDrive was announced I jumped all over it. The reasons were clear: I was a heavy Dropbox user and Google offers double the storage for half the price. Overall, I am pretty happy with the service, though there are some quality of life changes Google could make: for instance, it would be nice if I could control how much bandwidth the GDrive client uses at certain times of day; this is something that I have come to love in CrashPlan.

Still, it is likely that Google will add that functionality to the Mac client at some point in the future. There is one thing that they should fix now: Performance.

GDrive takes approximately four to five times as much RAM as Dropbox when idle or syncing. In my limited testing on both a 2012 Mac Mini and 2011 Macbook Pro have Dropbox using around 40MB GDrive uses 200+MB. While syncing Dropbox jumps to the high 50’s and low 60’s on my machines. while GDrive gets pretty close to 250.

I did some poking around and it seems that at least part of the GDrive client is written in Python, rather than C++ or Objective-C. This makes a lot of sense from Google’s perspective, since Python can run on Mac OS X, Linux, and Windows. Also, if you know anything about Google’s love for Python you’d know that most Googlers would write a Python script to make a cup coffee. I a am not suggesting that Python is a bad language, so keep the hate mail to yourself. However, this does feel a bit like a case of write once, suck everywhere.

To be clear, this issue is not enough to get me to quit the GDrive just yet, but it does seem like a little more effort could have been put in here.


Simply Loading TableViewCells from a Nib —

UITableViews drive a significant portion of iOS apps. Apple has provided some pretty great tools for developing decent looking apps based on them, but there are times when you might want to do something a little more stylish than what iOS provides. That’s when you probably consider writing your own UITableViewCell subclass or at least adding a category to UITableViewCell, though I find that is probably the less appropriate option in most cases. Getting your cells to look just right can be more than a little time consuming. Luckily, there is a bit of a shortcut you can take: loading the cells from a nib.

Before I show you how to do this, you should know going in that there are some drawbacks to doing this and that this is not an appropriate solution a some cases. Loading cells from a nib is less performant than just drawing the entire thing in code. Generally, you would not want to do something like this in a resource intensive app, such  as a game for example.  Ok, now that we have gotten that disclaimer out of the way, let’s get back to the point:

- (id)initWithStyle:(UITableViewCellStyle)style reuseIdentifier:(NSString *)reuseIdentifier
{
   self = [super initWithStyle:style reuseIdentifier:reuseIdentifier];
   if (self) {
       NSArray* nibContents = [[NSBundle mainBundle] loadNibNamed:@"SpecialCell" owner:self options:NULL];
       NSEnumerator* nibEnumerator = [nibContents objectEnumerator];
       NSObject* nibObject = nil;
       while ((nibObject = [nibEnumerator nextObject]) != nil) {
           if ([nibObject isKindOfClass:[SpecialCell class]]) {
               self = (SpecialCell *)nibObject;
               break;
           }
       }
   }
   return self;
}

The above code presupposes that SpecialCell is a subclass of UITableViewCell; I omitted the header for the sake of brevity. So, let’s get the obvious stuff out of the way. This method is overwriting initWithStyle and yes you could write a second method rather than overwriting that one. We have the normal if (self) check that we see in inits. All pretty much standard.

Ok, so what is actually loading the nib? Well, if you look nib is being loaded and its contents are being placed in the nibContents array. Once the the contents of the nib are all in the array, an enumerator is created based on it. After that we simply loop through all of the objects, assign self the the one whose class is SpecialCell and return it.
Pretty easy, right? Just keep in mind that this can be a source of slow down on your table and may not be an appropriate solution for your app, but this can be a good time saver for prototypes or non resource intensive apps. If you have any feedback I can found Twitter or Google+.


Objective-C Singletons —

A singleton is a way for developers to keep one and only one object of a class in existence for the entire lifecycle of an application; the nitpicky among you will note that there are portions of an app that might not have any instances of a singleton object, since it is common practice not create the singleton until you need it. Some example cases that you would use a singleton include: a player object for a game, a user object for a social app, and a shopping cart.

Creating a singleton is pretty simple:

@interface User : NSObject
static User* userSingleton;
+ (User *) userSingleton {
  if (!userSingleton) {
    userSingleton = [User alloc] init];
 }
return userSingleton;
}

Let’s walk through this. You declare a static user object called userSingleton, then whenver [User userSingleton] is called you check to see if that object is not null and either returns the existing object or alloc/inits the object, then returns it.

Ok, so that’s all well and good, but how do you actually use it. Well it’s simple. Let’s say our User class has a name property. We could access that with our singleton via:

[[User userSingleton] name];

Need to set the name?

[[User userSingleton] setName:@”Luke”];

Not bad, right? Also, note that all other messages can be sent via the same syntax, so:

[[User userSingleton] someMessage];

For those of you coming from a Java background sending a message in Objective-C would be called calling a method in Java.


Now you may have noticed that the above user object will have null values for all of its properties when it is first created and might want to be able to set some default values. For this example let’s assume that User has a few properties (name, fathersName, and saberColor):

static User* userSingleton;
+ (User *) userSingleton {
  if (!userSingleton) {
    userSingleton = [User alloc] init];
    [userSingleton setName:@”Luke”];
    [userSingleton setFathersName:@”Anakin”];
    [userSingleton setSaberColor:[UIColor blueColor]];
  }
return userSingleton;
}

As you can see, if the object is null, then we create it like before, but now we set some default values to its properties. Naturally, these values will be overwritten when you call their respective setters:

[[User userSingleton] setSaberColor:[UIColor greenColor]];


That’s pretty much all you need to know to get started with singletons in Objective-C. One thing of note about my code samples is that they assume you are using ARC, but you are not they still work; you will just have to include the proper retain/release calls. Hope this helps, please get in touch on Twitter or Google+.

***Update: An eagle-eyed reader pointed out to me that my sample here does not prevent you from creating a new instance of the object. So, if you created the object as I recommend but did User* badUser = [User alloc] init] you would have a new user object.  To get a true singleton (ie only one instance allowed) you would have to override alloc and a few other methods; The eagle-eyed reader recommends you see: http://cocoadev.com/index.pl?SingletonDesignPattern. Also, a few of you have gotten in touch with me asking why I did not show the GCD / block pattern. The reason for that is that I feel that it is too advanced for beginners but will write it up shortly. Thanks for all the feedback.


Programming Pitfalls: Android Keystore Files —

Programming Pitfalls is a series that aims to help new and seasoned developers avoid common and at times terribly painful programming errors and other missteps.

Ever submit an Android app to the Market… er I mean Play Store? If you haven’t I hope you do (mobile development is a lot of fun), but if you have do you remember that .keystore file Eclipse had you make? You don’t? Well, you’re in trouble. If you don’t find that file you will never be able to update your app. Poor design on Google’s part? That argument could be made, but the point of the system is to ensure that no one, other than you,  can submit an update to your app; imagine what would happen to mobile security if a malicious entity were able to submit a virus laden update to Angry Birds?

My recommendation is that you back up you key to a remote service, such as Dropbox or even GMAIL works. Just make sure that it is something that is in the cloud and have mutiple copies of your keystore in multiple places.

Hope this saves you some pain in the future.