Archive for Objective-C

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.

NSTask 100

I’ll get right to the point here. Reinventing the wheel is bad. Period. End of sentence. If you have a requirement that can be met by an acceptably licensed open-source software project and you are not using that project, then you are likely adding unneeded complexity to you project; you are certainly adding development time and therefore cost to the project.

Recently, I have been spending a lot of time developing an internal Mac OS X application for a client. This is a large scale application that has a lot of very specific requirements; these requirements range for media conversions to data sorting. After spending a little time trying to create my own internal Objective-C classes for many of these functions, I started wishing that I could just call down to OS X’s underlying UNIX utilities.

Then I remember something that I had read in a Cocoa book almost a year ago: NSTask. I popped open Dash and got to reading the documentation on this awesome class. Basically, you can use NSTask to call down to a UNIX utility, pass it parameters as you would from the terminal, and deal with its output.

Let me show you an example of how this would work with one of my favorite GPL’d tools: LAME.

NSTask* lameTask = [[NSTask alloc] init];
[lameTask setLaunchPath@”PATH_TO_LAME”];
[lameTask setArguments:[NSArray arrayWithObjects:@”CRAPPY_AUDIO_FILE.wav”, @”NEW_AWESOMENESS.mp3”, nil]];
[lameTask launch];
<

That’s it. It really is that simple. Keep in mind that for this to work the user needs to have LAME installed on his box already for this to work and distributing GPL’d software with proprietary software can be legally jeopardizing, so read those licenses. Also, MP3 is an IP encumbered format and I am not suggesting that you should violate IP by using the above code; I am only using it as a fun and easy to understand example of using NSTask to call a UNIX tool/

I hope this helps somebody out, if you have any questions or comments, please let me know or comment below.

All About ARC

ARC (short for automatic reference counting) is one of the most talked about and interesting additions to the iOS developer toolchain. However, in recent conversations with other developers I’ve found that there are a lot of misconceptions surrounding the technology. Hopefully, this clears up some of the confusion.

The first mistake that people often make when talking about ARC is that they equate it to garbage collection in languages such as C# and Java. This is simply incorrect. Boiling it down to its most basic explanation, a garbage collector runs in your application and checks to see what objects are no longer needed and removes them. This means that garbage collectors are very convenient for developers, but they take a small (depending on the implementation) amount of resources themselves. ARC is a special setting that can be set from within XCode that tells the compiler to insert release statements for you. So, this means that when you have ARC enabled the compiler is following the same retain / release rules you would normally follow for your own memory management, but this only happens at compile time, so there is no performance hit and you never see that statements themselves. This is useful because the compiler is far less likely to make a mistake than the average developer, especially in tricky situations, such as those that arise with multiple autorelease pools.

The second common belief developers hold surrounding ARC is that all their projects should use it. For new projects, this makes sense as long as you don’t mind targeting iOS 4.3+. However, converting legacy projects to use ARC can be a little hairy and like all magic that is made for developer convenience, when ARC causes a problem, it tends to be a tough one. Of course, that is not always the case and you mileage will certainly vary, but this is something to consider before hitting that shiny convert button.

Lastly, a number of developers that I have spoken to are under the mistaken impressions that all libs or external projects that you project is taking advantage of must be compatible with ARC for your codebase to use ARC. This is not the case. You can toggle ARC on and off for individual projects within your project (I know that sounds weird to me too) and safely use your legacy C libs or non-ARC Objective-C frameworks.

Overall, ARC is a great addition to the iOS developer’s toolbox, but it is like any other new technology and should be understood for what it is and adopted when appropriate.

Tutorial: Recording Media with QTKit for Mac OS X

Mac’s are very popular among creative professionals ranging from the user interface designer who designed your favorite iPhone app to the starving videographer who is just starting to break into the field via Youtube and Vimeo.

Recently, I have taken the plunge into Mac OS X application development and had a need to implement a number of multimedia functionality into the application: recording video via a built in or external camera and recording audio via the built in or external microphone and a number of other things. One way to this with a minimum level of effort is to use Apple’s QTKit; for those not familiar with Apple technologies QT stands for Quick Time which is Apple’s entrant into the multimedia player space.

There are number of things that you can do with QTKit but I am only going to focus on recording video and audio for this post. Additionally, I am making some assumptions about you, my reader: I assume that you know how to add a framework to an XCode project, I also assume that you know at least a introductory level of Objective-C and will not providing samples of what I consider boilerplate code.

Ok, so let’s get to it. Once you have imported QTKit, open the header file the class that you want to deal with the recording and declare some variables like so:

QTCaptureSession* session;
QTCaptureMovieFileOutput* fileOutput;
QTCaptureDeviceInput* videoInput;
QTCaptureDeviceInput* audioInput;

You are also going to want to create an NSButton to receive a click from the user. Jump into your implementation file and it’s time to start using those objects and making some more to actually determine how capable the system is of recording media. The following code is probably best put in an awakeFromNib or some similar function:

QTCaptureDevice* videoDevice = [QTCaptureDevice defaultInputDeviceWtihMediaType:QTMediaTypeVideo];
if (videoDevice) {
videoInput = [[QTCaptureDeviceInput alloc] initWithDevice:videoDevice];
...
}

Ok, so what we’ve done here is create videoDevice and set it to refer to whatever the default video recording device is for the user’s systems; I would be willing to gamble that you will be dealing with the built in camera pretty much all the time, but even if some silly user out there is doing something well… silly QTKit does a good job of abstracting specific hardware concerns away. I’ve omitted a good deal of code from my implementation above that basically does some safety checks and checks to see if the once device that you have found can also do audio recording and if it can assigns it that duty as well. These checks are mostly BOOL checks and simple checks from the hasMediaType method.

Once you have your input device / devices configured it is time to actual configure how the media will be recorded:

QTCaptureConnection* connection;
NSEnumerator* enumerator = [[fileOutput connections] objectEnumerator];
while ((connection = [enumerator nextObject])) {
QTCompressionOptions* options = nil;
if (mediaType isEqualToString:QTMediaTypeVideo]) {
options = [QTCompressionOptions compressionOptionsWithIdentifier:@”QTCompressionOptions240SizeH264”];
} else If ...
}

Basically, all this code does is create a few objects and loop over some data (I know that’s a pretty hardcore oversimplification but from an implementation standpoint, that is all you really need to know) and then determine how to encode the data to be output. Again, I have shown the code for the video, but the code to encode the audio is very similar.

In the last code chunk I neglected to explain what fileOutput was. Simply put it is an object that, as its name suggests, represents the resulting data after it has been properly encoded. So using that object we can do:

[fileOutput setCompressionOptions:options forConnection:connection];
[session startRunning];

And there you go. Your output will know be encoded to whatever you set in the above loop, so if you kept my code, your video would be in H264. The last line of code should be self explanatory, so I am just going to move on.

Your fileOutput object has one more important job to do: determine where to write the resulting file or if to write it at all. Remember when I recommended that you create a button and an IBAction? Well, you are going to use it now. Put the following code in your IBAction:

[fileOutput recordToOutputFileURL:[NSURL fileURLWithPath:@”/Users/share/movie.mov”]];

Basically, all this does is tell you fileOutput object where to write its data. Fair warning, that last code sample breaks Apple’s new sandboxing rules for the Mac AppStore, so if you want to be in the Mac AppStore, you are going to have to write the data within your application’s own sandbox; see Apple’s developer docs for more details on the new sandboxing rules. Also, the keen eyed coder will notice that my samples require manual memory management, but I did not include and release statements. Be sure to manage your memory properly.

If you have any questions or comments, sound off in the comments. Additionally, I can be reached on Twitter @dominucco.

Don’t Abuse My 3G!

Web services are great especially when coupled with rich clients, such as the iPhone or any other competing smart devices. However, more and more there is a dark-side to connected apps: developers abusing the ubiquitous connectivity of these devices to avoid having to save data locally.

 

Like most of my posts here, this one was inspired by a real-life experience. Today while working on a client application that had previously been out sourced I was trying to display the logged in user’s name. Simple, right? I should be able to do something like:

 

[User currentUser].name;

 

This code assumes that a singleton is being used for the current; there are other ways to get the same effect, but I personally like the singleton method the best. However, I surprised to see that my code produced a syntax error. Odd. So a took a look at the user model. Not only was the singleton approach not take there was no property called “name” or anything similar. In fact, I discovered that there was no way to either store nor pull the user’s name directly from the model. Confusion. Confusion is the only word used to describe my mindset.

 

So, since I had just inherited this app and had my predecessor’s contact info, I pinged him, assuming that there must be some clever way to get the info (the user’s name) locally that had not yet discovered; the app is fairly large after all. I was happy to quickly receive a response from the developer but was a bit shocked by the answer. There was no way to get this data locally. He had planned on just making a network call each time that he had to display the user’s name and number of common user attributes. That’s awful.

 

You might be wondering why I feel so strongly about this. Think about it. To pull data from a local store you have to call the local store and that is pretty much it. To get data from a web service you have to send a request to the service, the service has to process the request, the service has to reply, and finally the client has to parse the reply. to get the exact data that you had requested. Which would you rather as a user? It gets worse though with most wireless carriers instituting data caps on their customers this lazy way of dealing with data can actually cost the user money!