Archive for iOS

Crisis Coding: Stop The High-Res Madness

As someone who lives less than five miles from the Atlantic ocean in NJ, I’ve been having a bit of a bad time recently due to  Hurricane Sandy. Luckily, I was not harmed nor were any of my loved ones in the crisis. I did, however, notice something important: even  my non-techie friends and relatives were glued to their smart phones, hoping to hear some news about the storm, find out when their vital services (power / gas) might be restored, or (most importantly) check on their loved ones.

There are plenty of mobile apps that can be very helpful for handling a crisis, however, this recent crisis has shown me that there is something rotten in the state of app development — especially on the iOS side.

Let’s frame the scene a bit. During Sandy battery power was worth more than gold-plated platinum; for those of you unfamiliar with mobile development one of the most battery intense things most apps do is download data — especially image data. Up until today, I was out of power and the only access my fiance and I had to the outside world was out smartphones. Between us we have an iPhone 4S, a Galaxy Nexus, and a Lumia 900. We used all three phones to find pertinent data regarding the crisis.

I noticed some trends for roughly equivalent apps on each platform. The Windows Phone apps tended to load the fastest with the Android apps loading about as fast — I had no tools to do any real benchmarking, so these observations are all anecdotal. Sadly, my iPhone did not perform so well. I wondered why for a few minutes. After all, they were all on  3G  (the LTE Nexus had LTE turned off to conserve power) and the Lumia which was on AT&T should have been at a distinct disadvantage since Sandy had already claimed one of the local AT&T towers.

The difference was not with the network or OS’s or devices. It was about priorities in the apps themselves. While the Android and Windows Phone apps focussed on providing pertinent data in simple text based lists, the iOS apps were constantly trying to download images alongside the data. These images took a long time to load and therefore used an unnecessary amount of battery power. Worse still, after I regained my power earlier today, I reopened the iOS apps in question and they committed what is in my mind a mortal sin of mobile development: they all tried to download ‘retina’ resolution images over 3G.

Ridiculous. I understand that high-res images can make an app look good, but there is no need to download them over the air. Still, if you insist on downloading images that large, then please only do so over wifi. This is especially true if you app is geared toward helping people in a crisis.

Smart Client / Dumb Server?

These last few weeks I have been writing here and posting elsewhere about Parse, a service that stands up a simple backend for mobile application developers to connect to their apps. There are lot of good things that can be said about Parse. Unfortunately, it is based on a sub-optimal development model: dumb server / smart client. For the purposes of this article I am defining this development model as putting all or most of the validation on the client and reducing the server to little more than a thin layer over the database. Some of my more experienced readers will have their own ideas as to why this development model is sub-optimal, but for the rest of you I am going to go through the two that I see as the most important / relevant for today’s mobile development landscape: inherit functional limitations and slowed update cycles.

 

Parse does a great job and is a joy to work with, as long as you are doing what it was designed to do: authenticate users and store some data. For instance, try to pull a random object from your Parse data store but ensure that you get the same object on every client while making only one network request per client; hint: it is not currently possible to do with one network request and you will have to make at least two. In my experience, the best network request is the one that was never made. Once you send data over the air, the integrity of your user experience is out of your control and we all know how unreliable 3G can be. Getting a little more specific to Parse, you are currently placed into a higher pricing tier if you make over a certain number of requests to Parse.

 

Let’s be real here. If we are talking about mobile development projects, then we are most likely talking about iOS. Unfortunately, getting an update to your iOS app approved can take weeks and the situation doesn’t look to be changing soon: Windows 8 RT is adopting a similar review model and Android developers who target Amazon’s app store are subject to a similar review period as well. That’s bad enough taken alone, but consider that most software has bugs and that there is a correlation between the complexity of the code and the number of bugs in that code; that is why we try to follow KISS (keep it simple stupid). Given that, there is a clear incentive to keep the code on the client as simple / elegant as possible. However, running a dumb server and forcing validation on the client prevents that in most cases; your client code will have to take on most of the validations that the backend code would have had, thus making it that much more complex. Imagine a bug that you can’t get a patch out for in less than twenty days but worse still you can’t guarantee that all of your users will update as soon as possible or even at all. With a real backend API you could make the fix and the bug would be taken care of for all users in most cases.

 

These are real risks and either of them can derail your project. Should you just avoid these type of things wholesale? Maybe… but there is certainly an argument to made for extremely low budget projects or prototypes.  Let me know what you think on Twitter or Google+. Also, if you have not already, pick up your copy of Code Journal today either from the Mac App Store or direct.

A Look at PFQuery

Querying data is a pretty common task for most if not all mobile apps. iOS and Android have made the work pretty easier for developers, but Parse has thrown their hat into the ring to make it even easier for developers who choose to use their development tools and backend system; yes, I know this sounds a little like a commercial, but I am genuinely excited about this functionality and no I have no business or personal relationships with Parse or anyone therein.

PFQuery is a simple class that, as its name suggests, allows you to query your Parse dataset and getting data returned based on certain criteria. No need to stand on ceremony, let’s take a look at some code:

- (void) someMagicalFunction {
	PFQuery* query = [PFQuery queryWithClassName:@"SomeClass"];
	[query whereKey:@"SomeProperty" equalTo:@"MagicString"];
	[query findObjectsInBackgroundWithBlock:^(NSArray* objects, NSError* error) {
		// do something with the objects

	}];
}

And now for you Android fans:

void someMagicalFunction() {
	ParseQuery query = new ParseQuery("SomeClass");
	query.whereEqualTo("SomeProperty", "MagicString"
	query.findInBackground(new FindCallback() {
		public void done(List< ParseObject >objects, ParseException e) {
		// do something with objects
	});
}

Yup, that’s it. It really is that simple. If you want to know more take a look at the Parse docs. For those of you that are critical of Parse, I will be doing more than just code samples with it; in fact I have found a few deficiencies that I will be discussing in a future blog post.

Bad Synchronous Call! Bad!

Back in the dark old days of Commodore 64 and its brethren computers were pretty much all synchronous; instructions executed one after the other, one at a time. It was a simpler time. Users did expect a responsive UI during slow operations or so I have been told. Wondering what a slow operation is? Well, how about any sort of IO? or large data transfer? or how about just pretty much any data transfer over 3G? Of course, there are other cases of long operations but no need to open old wounds….

Now I can hear you already, arguing ‘the platforms today are so much more multi-threaded / multi-core by default I don’t have to worry about writing asynchronous code.’ Well sir (or madam), you are dead wrong. It is true that or more modern platforms have done a lot to run their internal operations in a thread safe / optimized way, but there are a lot of cases where YOU MUST make your code asynchronous. The platform is not going to waive a magic wand and make your operation run asynchronously. Need an example? Here you go:

UIImage* image = [UIImage imageWithData:[NSData dataWithContentsOfURL:someURL]];

Looks reasonable, no? Wrong! That code though deceptively simple is actually very bad. Let’s take a look at what is actually happening in this little one liner:

NSData* imageData = [NSData dataWithContentsOfURL:someURL];
image = [UIImage imageWithData:imageData];

Still pretty simple, right? That’s the exact same functionality as the one linear above and the same problem. Take a closer look at that first line. Pretty simple, right? All it is doing is reading the contents of a URL (in this case an image) downloading the data, and creating an NSData object from it. See the problem yet? That is all happening in order synchronously. If the network is slow or the server is slow to return, the UI on your lovely app will lock for a second or so. Bad UX. Very bad. It is important to note that this code is using one of the most direct ways to create an image from an external service provided wholly by Cocoa. Not to hit this too hard, but the platform vendor’s framework (Cocoa in this case) is not doing anything magical to prevent this from happening. Your code is causing the problem and you have to fix it — yourself.

Oh? You actually want to see a correct version of this code? Well, ok. What needs to happen here is that the image needs to be dealt with asynchronously. I like to use the popular (albeit somewhat dated) iOS / Mac library ASIHTTP to accomplish this. For one request it is really easy:

ASIHTTPRequest* request = [ASIHTTPRequest requestWithURL:someURL];
__weak ASIHTTPRequest* _request = request;
[request setCompletionBlock: ^{
UIImage* image = [UIImage imageWithData:[_request responseData]];
}];
[request setFailedBlock: ^{
// handle failure
}];
[request startAsynchronous];

Not too bad, right? Just a quick walkthrough. If you are new to Cocoa you might not be familiar with the concept of blocks. It’s a pretty big topic and worthy of its own post (or series of posts) but they are similar to closures in other languages. Also, the “__weak” is to prevent a retain cycle for developers using ARC; if you are not using ARC in your new iOS or Mac OS X projects, consider it. Ok so what if you have to deal with a large number of images for something like a UITableView full images? Well check this out:

ASINetworkQueue* q = [[ASINetworkQueue alloc] init];
[q setDelegate:self];
[q setQueueDidFinishSelector:@selector(networkQueueDidFinish:)];
[q setRequestDidFailSelector:@selector(requestDidFail:)];
[q setRequestDidFinishSelector:@selector(requestDidFinish:)];
for (int i = 0; [someArrayOfImagesURLS count]; i++) {
ASIHTTPRequest* imageRequest = [ASIHTTPRequest requestWithURL:[someArrayOfImagesURLS count]];
[q addOperation:imageRequest];
}
[q go];

// delegate methods
- (void) requestDidFail:(ASIHTTPRequest *)request {
// something bad happened -- handle it!
}

- (void) requestDidFinish:(ASIHTTPRequest *)request {
UIImage* image = [UIImage imageWithData:[request responseData]];
// do something with the image
}

- (void) networkQueueDidFinish:(ASINetworkQueue *)q {
// do something magical when the queue is done
}

Ok so all that has changed is that we iterate through an array or URLS for the images, create ASIHTTPRequests based on them, add them to our operation queue, and deal with the delegate methods. One thing of note is that there are separate callbacks for when each individual request finishes and for the queue itself and if you fail to implement one of those required delegate methods your app will crash.

Hope this helps someone. I am going to be posting more about writing asynchronous code to best take advantage of the multi-threaded / multi-core nature of our favorite platforms. Stay tuned for a look at this type of thing on Android! Find me on Google+ or Twitter if you have feedback.


WWDC 2012 Keynote Let Down

Earlier today I hosted Coder Radio with Chris Fisher of Jupiter Broadcasting and in the episode we discussed my reactions as a developer to the WWDC keynote this year (2012). First things first. I did not attend WWDC nor have I installed the iOS 6.0 developer release, so some of my information may be incomplete; I have to do this in this way due to Apple’s developer NDA. You can listen to the show to hear what I didn’t like, but I’d rather go through a few things that I would like to have seen that to my knowledge aren’t coming.

Inter-app Communications
This is by far my largest pet peeve with iOS development and using iOS. Why isn’t there are robust way for apps to work together and share data; within reason of course. Android has a version this in the form of “intents” and Windows Phone 7 has a incredibly powerful system called “contracts”. This really gets to me when I consider that iOS is a BSD system yet does not adhere to the UNIX philosophy of allowing many small applications to work together to do big things; yes, I know that iOS apps tend to be smaller in scope than their desktop counterparts but to date there is no real way for them to work together. There is so much functionality that cannot easily be done on iOS due to this restriction.

Widgets
On my Android and Windows phone I can glance at the screen and get the latest tweets, view other data (such as a stock ticker), and play a song, or begin or pause listening to an audiobook. On iOS, almost all of those things require me to launch separate apps. That’s silly not to mention a bad user experience. I know there are definitely battery life concerns if you have too many widgets open, but there is no reason that Apple can’t add some sort of restricted mode for simple widgets to run in.

Siri integration
Ever since I got my hands on my 4S I have been waiting for a full Siri API. Apple has been working on it, but to date there is no fully functional Siri API for third party developers. This is understandable given how often Siri simply does not work but it is still a shame.

That’s all for now. Now I can finally take a look at the dev preview! For feedback please find me on Google+ or Twitter.

Programming Pitfalls: Bit in the ARC

Apple’s ARC (automatic reference counting) for Mac and iOS devices is intended to make Cocoa development easier. For the most part it does. However, in using it I have encountered a bit of a pitfall: by default the compiler does not optimize your code in debugging but uses its most optimized setting for release.  What does this mean? Well, the more you tell it to optimize your code, the sooner it will release objects for you, which can lead to some issues. To be clear the default settings for each mode are zero optimization and the most possible optimization respectively.

Basically,  a lib I was using was working fine in testing but was throwing BAD_ACCESS errors when running in release mode. After over an hour and half of investigating I found:

The screenshot is showing XCode’s “Build Settings” screen, where you can clearly see that a different level of optimization is being used for the two different modes.

From here the fix is pretty easy: tune down that optimization level. Alternatively, you could dig into the code that is having the issues, but that might turn out to be something of a premature optimization for most needs.

Hope this helps someone. You can find me on Twitter or Google Plus.

Programming Pitfalls: NSAutorelease Pools on iOS 4.X

iOS 5 has brought a lot of quality of life improvements in terms of memory management and the general iOS development workflow, assuming you are on the latest tooling. However, nothing is free and there seems to be a little bit of a pitfall that you might hit if you are testing predominantly on iOS 5.x: iOS 5 seems to deal with autorelease pools a bit differently than 4.

Here’s the situation:

- (void) viewDidLoad {
  [super viewDidLoad];
  [self performSelectorOnMainThread:@selector(yourMagicalMethod) withObject:nil     waitUntilDone:NO];
}

- (void) yourMagicalMethod {
  // do some magical stuff and set some objects to autorelease
}

This will run fine and without complaint on iOS 5. However, on iOS 4 it throws some errors in the log at runtime regarding no autorelease pool being set and leaks every object you set to autorelease in yourMagicalMethod. If that isn’t enough to crash your app, then your app will be in a highly unstable state and will be prone to crashing the next time you do something even somewhat intensive, such as call the camera.

I did some sleuthing with Instruments and found that yes on 4.x those objects are all leaked and yes they are not on 5. Luckily there is an easy solution that doesn’t involve any crazy version checks or (God forbid) compiler macros:

- (void) yourMagicalMethod {
  NSAutoreleasePool *pool = [[NSAutoreleasePool alloc] init];

// do some magical stuff and set some objects to autorelease

  [pool release];
}

That’s it. All you need to do is create an autorelease pool in scope and release it. Both iOS 4 and 5 will be happy. I don’t know why this issues exists and I’d love to find out if you do. If you have questions or comments, I am on Twitter and Google+.

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+.

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+.

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+.