In this continuing series on my own transition from a Mac application hacker to microISV (Independent Software Vendor), I am going to demonstrate how to create your own file format for your application. You’ve probably seen these types of files in popular applications such as iMovie HD (06′) or GarageBand or even xcode in which the actual files used are, behind the scenes, folders that the operating system treats as regular files. These folders/files have a special bit set on them that tell OS X how to deal with them. The goal of this post is to demonstrate how you can do the following:
- Create your own file format with your own file extension
- Register your file format with the operating system
- Provide application loading of your file that’s been double clicked in the Finder
- Write data and preferences back out to your application file
- Add resources such as media files to your application file
I often find and therefore come to expect common problems in Cocoa to be easily solvable, however, there are times, like this, where I am a bit disappointed that the problem can be so difficult. All I need to do is copy a file. This is a simple task right? All you need is NSFileManager and a call to - (BOOL)copyPath:(NSString *)source toPath:(NSString *)destination handler:(id)handler and you’re good to go. Not so fast, city slicker. This one is going to take a bit more effort cause you want one of them fancy new-fangled progress indicators to show how much of the file has been copied. Well, if you want Cocoa to help you, you’re out of luck cause NSFileManager won’t do that for you, but with a little bit of effort you can get it to work with some… gulp… C APIs.
Undo support in Cocoa is fantastic but for those who have tried to mix it with Core Data know that it can be a bit frustrating. Generally, undo support can be ignored in most applications and it will “just work”. But when Core Data is added to the recipe then things get a bit confusing and more complicated.
In this post I continue to address topics of relevance to Macintosh programmers who are, like me, moving from being hackers to becoming independent software vendors (micro ISV). Today I am going to address adding copyright and version information to your about dialog and show you how you can update these dynamically. I also cover a few tips on formatting the text in your about dialog. There is more than one way to achieve these things, but my hope is to help others out there who need to accomplish these things and have no prior experience doing them on the Mac.
NSDecimalNumber is Objective-Câ€™s solution to numbers that need to be very precise. The documentation defines it as:
NSDecimalNumber, an immutable subclass of NSNumber, provides an object-oriented wrapper for doing base-10 arithmetic. An instance can represent any number that can be expressed as mantissa x 10^exponent where mantissa is a decimal integer up to 38 digits long, and exponent is an integer from â€“128 through 127.
If you are dealing with currency at all, then you should be using NSDecimalNumber. However, since it is immutable and definitely not a primitive then it is difficult to use right? Well â€” yes â€” a bit. But if you do not want to see your $9.50 item displayed as $9.49999994 or something then you are better off using NSDecimalNumber right from the beginning. Otherwise you are going to be converting to it later and that is a LOT more painful.
For the past five or six months, I have been developing an application for the Mac that I intend to release for sale in the near future. Though you could probably call me a switcher, to my credit I was a Mac user all through college and would have remained so had the job market been a bit more supportive of that desire when I finished school, but all along I’ve wanted to become a Macintosh developer. That time has finally come.
Key Value Observing/Key Value Coding (KVO/KVC) is probably one of the most powerful and most under-utilized features of Objective-C. Here are a couple of examples of how to get the most out of it
When a call is made on an object through Key Value Coding such as [self valueForKey:@"someKey"], numerous attempts are made to resolve the call. First, the method someKey is looked for. If that is not found then the iVar someKey is looked for. If neither of those are found, then one last attempt is made before presenting an error. That last attempt is a call to the method -(id)valueForUndefinedKey:. If that method is not implemented then an NSUndefinedKeyException is raised.
valueForUndefinedKey: is designed so that when you request a value from an object using -(id)valueForKey: the object has a last chance to respond to that request before an error occurs. This has many benefits and I have included two examples of those benefits in this post–Core Data Parameters and Data Formatting.
System programming is one of the more interesting topics to me because it seems like it’s the hackers domain. When I first got into programming I always wanted to see if I could make the computer do something that nobody else anticipated it could do. I think it was probably just from watching too many hacker movies. Even the Matrix (the first one, not those other two contorted kill joys) had this affect on me that somehow I could beat the system because as Morpheus put it,
I’ve seen an agent punch through a concrete wall. Men have emptied entire clips at them and hit nothing but air, yet their strength and their speed are still based in a world that is built on rules. Because of that, they will never be as strong or as fast as you can be.
Man! I loved that movie the first time I watched it. A world without rules? Or more specifically a world where you set the rules by your most awesome hacker powers. Sweet!
But alas, as I’ve proceeded and matured (I hope) in my programming abilities, this whole area has become much less glamorous as I realize that hacking is really about finding vulnerabilities in other people’s code. That’s really not that exciting to me, but system level programming remains interesting and a good place to start is to look into who the users are on my system. Time to use Identity Services. And in this intro I’ve written a very basic password cracking system.
Error handling is rarely fun. I find myself often re-coding a method after I realize that I need to handle one error condition or another. Usually, error handling involves either try/catch or some return code strategy. Neither of those is pretty or easy to maintain. For Objective-C development, however, there is another option — NSError.
As I am getting toward what I think is the end of coding for an application I hope to release soon, the nitty gritty work of fixing leaks, optimizing code, and squashing bugs has become the majority of what I’m doing now. Gone is the fun part of the application development process where I was creating features and solving new problems. It is now drudgery and focusing requires diligence. I know that the rewards are worth it as these final steps are what give an application stability and make it shine, but getting through it can be nothing but toil. Fortunately with the developer tools that shipped with Leopard, Apple has made this work much easier to handle in a little application called Instruments.
When developing an application in Objective-C and using Cocoa, there is a lot of “magic” that happens in the background. As we get more comfortable with the language and the APIs, we begin to discover the source of that magic and understand not only WHY it works but HOW it works.
One of those areas is the initialization and callbacks from the nib files to my code. Normally, when I want a controller to do something after the NIB/XIB has loaded, I add the method -(void)awakeFromNib and know that I will receive a call when all of the connections into the NIB/XIB are complete. But on what object does this get called and how?
I am currently working on an application that needs to set markers in audio and video tracks. While it’s easy to find a marker visually in the video tracks, it wasn’t quite so clear as to how to set a marker in an audio track. In this tutorial, I’ll demonstrate how to create an audio scrub utility that will play a short audio clip when you drag an NSSlider. It shows the current time code of the track while you update the slider.
In our continued efforts to demonstrate different ways to use Core Animation, we have noticed different effects you see in OS X itself that present an interesting challenge to duplicate. In a previous post, we demonstrated how to shake a login window similar to the way that OS X shakes the login window when the user enters the wrong password. This time, we’re going to demonstrate how to do what we’ve dubbed the Dashboard Effect.
I’m not sure this is the best name for it as some people may think we mean the ripple effect you see when you drop a new Dashboard widget on the screen, but what we mean is the way in which the Dashboard widgets that are already employed in Dashboard fly in and out of view when you enable and disable Dashboard. Enable Dashboard now and watch your widgets fly in from offscreen. Then disable it and watch the widgets fly out again. This is what we mean by the Dashboard effect and this is what we set out to duplicate.
This article is designed to serve multiple purposes. First, it is to educate which I hope that it will. Secondly, it is a personal memory so that if (when!) I run into this issue again, I will be able to use Google to find this post and remember why I am an idiot and why the default settings for things are not always the best settings.
First as always, here is the project that goes with this article.
If you run this application you will see that it does basically nothing. The interesting part of this app is how it crashes. To crash this application, perform the following steps:
- Open the application.
- Select the Application menu.
- Select the About window.
- Close the About window.
- Open the Application menu again.