Archive for Objective-C

Programming Pitfalls: Circular Imports in Objective-C

PitfallI spend a lot of time in XCode working in Objective-C for iOS and Mac OS X projects. In many ways, Objective-C has become my “native language” in terms of programming languages. Still, that doesn’t mean that I can’t make really silly mistakes when working in that language. In fact, through the magic of GitHub you can see the mistake in real-time in my open-source Cocoa / Cocoa Touch networking library, MDNetworking.

The mistake is, like the best dumb mistakes, small and simple but can take more time than I’d like to admit to notice and resolve. Take a look at this pseudo-code sample for what went wrong:

#import "Foo.h"
#import "Bar.h"

@implementation Foo
 // CODE
@end

 

#import "Bar.h"
#import "Foo.h"

@implementation Bar
// CODE
@end

That’s it. That’s all you need to do to reproduce this programming pitfall. As always, I hope this has been illuminating and entertaining for you and please do follow me on Twitter.

MDNetworking: My Little Networking Lib

Disclaimer: This is in no way a 1.0 codebase and I strongly recommend against you using this in production.

Summary: MDNetworking is a small Apache 2.0 licensed Cocoa / Cocoa Touch library. It is intended to be suitable for use on iOS7+ and Mac OS X 10.8+ but it may in fact be possible to get it working on older version of iOS and OS X. My intention in creating this library is not to make yet another heavy Cocoa networking framework that is going to solve the meaning of life and the world’s problems. I merely want to present a relatively simple and easy to use facade of NSURLConnection and the like.

Contributing: I’m open and welcome contributions from the community, however, any contributions that don’t adhere to the present code-style will be rejected.

Pallet Town: Intro to AFHTTPClient Part 1

Pallet TownWelcome to Pallet Town! Pallet town is going to be an ongoing bi-weekly look at various development technologies and techniques from the perspective of someone new to that technology. For those who might know or (God forbid) are too young to get the reference, Pallet Town is the first town in the original Pokemon games for the Nintendo Gameboy.

This week we are going to take a look at getting some simple networking done with the new hotness in iOS networking frameworks: AFNetworking. To be specific we are going to focus on one of its more important classes: AFHTTPClient Now there are is a little bit of a prerequisite here, we are going to go ahead and assume that you have already added AFNetworking to your iOS project and we are also going to assume that we are going to use ARC.

For starters, let’s take a look at how we instantiate the AFHTTPClient:

Now that we have our client, let’s say we want to make a simple RESTFul GET call; this sample builds a bit on our Pokemon themed ASP.Net MVC web app from the last installment of Pallet Town. Ideally, this call would just get all the Pokemon available on the API; this of course assumes you followed the normal MVC patterns in your routing on the API. Here’s the code:

- (void)getAllPokemon
{ 
	AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"SOME_URL_STRING"]];
	[client getPath:@"api/pokemon/" parameters:nil success:^(AFHTTPRequestOperation *operation, id responseObject) {
			NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
			NSLog(@"Request Successful, response '%@'", responseStr);
		} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
				NSLog(@"[HTTPClient Error]: %@", error.localizedDescription);
	}];
}

That was fun but let’s make things a little more complicated. Let’s say you want to pull a particular Pokemon via its Id. That’s still a GET request but takes a parameter like so:

- (void)getPokemonById:(NSNumber *)pokemonId
{ 
	NSDictionary* parameters = @{@"Id" : pokemonId}
	AFHTTPClient* client = [[AFHTTPClient alloc] initWithBaseURL:[NSURL URLWithString:@"SOME_URL_STRING"]];
	[client getPath:@"api/pokemon/" parameters:parameters success:^(AFHTTPRequestOperation *operation, id responseObject) {
			NSString *responseStr = [[NSString alloc] initWithData:responseObject encoding:NSUTF8StringEncoding];
			NSLog(@"Request Successful, response '%@'", responseStr);
		} failure:^(AFHTTPRequestOperation *operation, NSError *error) {
				NSLog(@"[HTTPClient Error]: %@", error.localizedDescription);
	}];
}

Getting Pokemon from the server is a lot of fun, but you know in the age of Minecraft, I like to  be a little more creative than just working with the set number of Pokemon that Nintendo provides. Tune in for our next installment to see how to POST my very own legendary Pokemon to the server!

UILocalNotification 100

Tomato SoupThere are a lot of cases where you will want to notify your user of some event of reminder without actually setting a formal alarm in their Alarm app. The standard solution most developers seem to take in these situations is to setup something like Urban Airship and fire off a push notification – this costly and shares the user’s data for no reason. Using
iOS’s UILocalNotification, you can pop a push-like notification without worrying about the hassle and potential cost of a push service and without sending any user data over the air. Checkout how easy it is to fire off a simple notification from this simple from my newly released Pomodoro timer Tomato Soup:

- (void)createNotificationForPomo:(TSPomodoro *)pomo
{
	UILocalNotification* notification = [[UILocalNotification alloc] init];
	notification.fireDate = pomo.fireDate;
	notification.alertBody = [NSString stringWithFormat:@"Nice work! Pomodoro: %@ is complete!", pomo.title];
	[[UIApplication sharedApplication] scheduleLocalNotification:notification];
}

// Now let's remove all notifications
- (void)removeNotifications
{
	[[UIApplication sharedApplication] cancelAllLocalNotifications];
}

Notifications like the one created above will still fire if the app is in the background, however, if you don’t want them to fire if the app is active, you will have to deactivate them on willResumeActive.I hope this helps you and that you reconsider how often you send user data over the air and use UILocalNotification as a simple alternative to push when appropriate.

Comments? Questions? Drop me a line on App.net, Google+, or Twitter. Also, pickup Code Journal.

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.


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

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

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