Cocoa Programming for Mac OS X (Ch 9-12)

Read part one here, part two here and get the book here .

The plot thickens!

Chapter 9, NSUndoManager.

For those wondering what that NS is doing everywhere, it comes from NeXTSTEP more information about it here.

This chapter is all about adding undo / redo capabilities to your application and maybe it’s because the current sample application is, well, a sample, but it’s rather easy to add this capabilities to your program. Also you get it integrated with the menu bar at no extra cost, the window shows that there are changes, and the undo and redo buttons come to live. The underlying mechanism relies heavy upon Key-Value coding which was discussed in chapter 7 , again demonstrating it power.

- (void)insertObject:(Person *)p inEmployeesAtIndex:(int)index
{
    NSLog(@"adding %@ to %@", p, employees);
    NSUndoManager *undo = [self undoManager];
    [[undo prepareWithInvocationTarget:self] removeObjectFromEmployeesAtIndex:index];
    if(![undo isUndoing])
    {
        [undo setActionName:@"Insert Person"];
    }
    [self startObservingPerson:p];
    [employees insertObject:p atIndex:index];    
}

Chapter 10, Archiving.

The sample application now tracks changes and when you try to close an edited window it asks if it should save its changes. So the logical next chapter is about adding this capability.

In this chapter we learn that the notion of an interface in .Net actually also exists in Objective-C, but it’s called a protocol and unlike .Net and Java you can have optional methods in a protocol so any method marked optional does not need to be implemented.

Archiving is coupled with the NSCoding protocol and the abstract NSCoder class, most of the time you’ll be dealing with the abstracted class which hides the underlying mechanism. Implementing this can be compared to the implementation in .Net. Though it requires less code to write since your object graph is stored automatically in a file. You can configure the extension and the icon from within XCode, it was also nice to see that OS X had automatically associated the extension with my application.

#import <Foundation/Foundation.h>
 
@interface Person : NSObject <NSCoding>{
    NSString *personName;
    float expectedRaise;
}
 
@property (readwrite,copy) NSString *personName;
@property (readwrite) float expectedRaise;
 
@end
 
#import "Person.h"
 
@implementation Person
 
-(id)init
{
    [super init];
    expectedRaise = 5.0;
    personName = @"New Person";
    return self;
}
 
-(void)dealloc
{
    [personName release];
    [super dealloc];
}
 
@synthesize personName;
@synthesize expectedRaise;
 
- (void)setNilValueForKey:(NSString *)key
{
    if([key isEqual:@"expectedRaise"])
    {
        [self setExpectedRaise:0.0];
    }
    else
    {
        [super setNilValueForKey:key];
    }
}
 
- (void)encodeWithCoder:(NSCoder *)coder
{
    [coder encodeObject:personName forKey:@"personName"];
    [coder encodeFloat:expectedRaise forKey:@"expectedRaise"];
}
 
- (id)initWithCoder:(NSCoder *)coder
{
    [super init];
    personName = [[coder decodeObjectForKey:@"personName"] retain];
    expectedRaise = [coder decodeFloatForKey:@"expectedRaise"];
    return self;
}
 
@end

Chapter 11, Basic Core Data.

You thought it was good, well it just gets better. All the code we still had to write to add undo/redo, change tracking and archiving to our application can be done without writing any line as illustrated with this chapter. Again we see the power of Key-Value coding.

Chapter 12, Nib Files and NSWindowController.

Nib files contain the state of the window designed with interface builder, this chapter tells you how you can postpone loading a window/panel to save memory and resources. It also how you can load classes (this includes Windows, custom classes, etc.) by their name. Much like the Activator in .Net.

- (IBAction)showAboutPanel:(id)sender
{
    BOOL successful = [NSBundle loadNibNamed:@"About" owner:self];
    if(successful){
        NSLog(@"Loaded nib from NSBundle");
    }
    else{
        NSLog(@"Unable to load nib");
    }
}

RaiseMan – Chapter 9.zip (72.21 kb)

RaiseMan – Chapter 10.zip (74.18 kb)

CarLot – Chapter 11.zip (43.54 kb)

RaiseMan – Chapter 12.zip (85.23 kb)

Cocoa Programming for Mac OS X (Ch 6-8)

View Chapters (1-5) here, get the book here .

The title of chapter 6 “Helper Objects” did not sound good. Whenever I find classes with the words Helper or Util in their name, this usually indicates a “code smell” and most of time the underlying problem is a leaky domain model. Turns out something completely different is the subject of this chapter, delegates!

They can be compared with delegates in .Net though they are being used in a different way. I’ll illustrate with a sample.

The TableView UI component deals with displaying data like a table, compare this with the .Net grid. What it displays however is not part of his responsibility, this behaviour can be added though by using delegates. The tableView has a delegate member which you can set, if that object implements methods which map to delegate methods of the tableView they will be called, otherwise they won’t. This means that you don’t need to implement everything, just what you need.

I think in .Net this behaviour would be implemented by using interfaces. So if you had your own grid component, it’s datasource could be set to something of type IDatasource which would provide the necessary functionality that would be called by the grid component.

Overall this is off course a powerful feature, though implementing it requires attention, misspelling the method name means that your method won’t be called and you won’t get any errors. The author states that the best way is to look at the documentation and copy paste the method signatures in your code.

Chapter 7 “Key-Value Coding; Key-Value Observing”.

A short chapter, only 12 pages, but it seems to be a core concept. If you have an instance variable foo in class Bar, you can have other objects be notified of changes to it. This can be compared to the .Net INotifyPropertyChanged interface and its interweaving with databinding. Since the observers call the methods valueForKey: and setValue:forKey: you need to make sure your code follows the strict naming convention to get this functionality.

If you are changing the observed instance variable in methods you need to call the methods willChangeValueForKey: before changing it and didChangeValueForKey after you’ve changed it to alert the observers of the change. If you find that too much work just call the setter of the instance instead of changing it directly.

- (int)foo
{
    return foo; 
} 
 
- (void)setFoo(int) x
{
    foo =  x;
}

A handy shortcut to write a property is to use the @property and @synthesize which do all the work for you, the above code can thus be replaced by a simple

@property(readwrite) int foo;

in the header file and

@synthesize foo;

in the implementation.

Overall familiar material, I’ve seen this in .Net and it’s available to me in Objective-C excellent! There even is a valueForKeyPath: method that traverses the object tree i.e: spouse.scooter.modelName.

Chapter 8, NSArrayController.

In this chapter all you’ve seen so far comes back, but in a different way. In the previous chapter you had to write a lot of plumbing to get your list of objects to display and be editable. The NSArrayController however can help you on this, it allows user interface components be bound using chapter 7’s techniques. You can automatically add and delete objects, display them and edit them without writing code, just hook everything up.

To solve challenge 1 for this chapter edit the sortKey to be personName.length and selector to compare:. I’ve attached the code for those interested.

RaiseMan – Chapter 8.zip (69.85 kb)

KVCFun – Chapter 7.zip (53.38 kb)

SpeakLine – Chapter 6.zip (59.93 kb)

DelegateResize – Chapter 6 Challenge 1.zip (47.51 kb)

ToDoApplication – Chapter 6 Challenge 2.zip (57.66 kb)

Cocoa Programming for Mac OS X (Ch 1-5)

Earlier this week I purchased this book: Cocoa Programming for Mac OS X since I wanted to get an introduction on how to develop native applications for OS X. It’s the most recently published one on the issue and got mentioned on MacRumors.

In a series of small posts I’ll put down some notes for myself here and anyone who is interested can read along.

Chapter one gives you some background on the language, what tools will be used throughout the book and explains the different kinds of frameworks available in Cocoa. Nothing special here, I want to write code!?

And there’s chapter two, the author guides you through your first Objective-C program. The interface of XCode and Interface builder (IB) are explained. I was surprised to read that any method you write is public and every instance variable is protected. Also instance fields which are connected through the IB are called outlets and you designate them accordingly in your header file. Methods that can be used by user interface objects are called actions.

#import <Cocoa/Cocoa.h>
 
@interface Foo : NSObject 
{ 
    IBOutlet NSTextField *textField; 	
}  
 
- (IBAction)seed:(id)sender; 
 
- (IBAction)generate:(id)sender;

The – before the two method declarations indicate that it’s an instance method, class methods are designated with a +. The IBAction and IBOutlet are hints for the IB. NSObject is the base class for every other object. The id ‘type’ (don’t know if I am allowed to call it that way) is a pointer to basically anything.

Chapter three digs a little deeper on objects and classes. Calling methods on objects looks a bit different if you come from a Java or C# background.

MyClass* myInstance = [[MyClass alloc] init]; 
 
[myInstance doStuff]; 
 
[myInstance doStuffWith:bar];  
 
[myInstance doStuffWith:bar using:foo];

The first line first calls the constructor and init method. Both are inherited from NSObject and on the second line I call the doStuff method on myInstance. It takes some getting used to, also note the naming convention if you’re a .Net programmer methods start with a capital. Method names are also called selectors. On the third line I assume I’ve an other object called bar and it illustrates how you pass parameters with method calls. Finally the last line illustrated how multiple arguments are passed along.

I raised an eyebrow when I read that if you call a method of on objects which points to nil (null), no exception will be raised. Sure, it allows you to omit those tedious if(!= null) checks but I’ll probably pull out my hair when I’m writing more real life application and it’s not responding the way it should.

One final note for this chapter, calling methods of your base type is done in the Objective-C world by using the super keyword.

Chapter four talks about memory management. This was fairly new for me, I knew about it but I’ve only written programs in .Net (C#, Vb.Net, managed C++) or J2EE (Java) and both environments come with the garbage collector (GC) which manages memory for you. Mac OSX 10.5 introduced the GC as well, but it’s an option. If you turn it on your application will only run on 10.5 and later, so if you want to target previous versions you’ll have to release and retain yourself.

It was an interesting read, I never had seen an example of how memory can be managed in code you write. I’ll probably just turn the GC on for stuff I write. The chapter ends with stating that you should now have a basic understanding of Objective-C and Cocoa and that the next chapters will focus on the different frameworks you can use to build your applications.

Chapter five introduces some user interface components available in the IB (buttons, textboxes,…), nothing big here although I encourage you to write the challenge application. Challenges in the book are exercises which you should be able to write.

Attached you find the challenge exercise from chapter five (countline), the guided application (speakline) also from chapter five and the lottery application from chapter three and four.

CountLine.zip (55.52 kb)

lottery.zip (16.43 kb)

SpeakLine.zip (52.62 kb)

Also I apologize for the layout of the code in this post I’ll fix that as soon as I can, Objective-C isn’t supported by default 🙂 .

Select boot type

Got a new desktop at work (a massive quad core !) and during the installation I was greeted by the following message.

Mac keyboard and mouse

I wanted to use my PC screen when I’m sitting behind my “desk” and working on the MacBook, choosing between 13″ and 22″ display is easy. The side effect of that was that my head is constantly on a 45 degree angle compared to my body which tends to be less than comfortable after a while. I couldn’t connect my keyboard with a PS2 connector since there is no port of that type on the MacBook or for that matter any laptop I know of. So the Apple stakeholders just got a bit richer and I now have a wireless Apple mouse and keyboard.

Installation is child’s play, unbox the items, add the included batteries in their container, set up the bluetooth devices (can be found on the upper right corner of your desktop), turn the device on and you are done.

Bluetooth Configuration

The keyboard is the same as the one on the MacBook so I’m loving it. The MightyMouse does it job (even right clicking yay!) but the buttons on the side are a bit harder to work with. I don’t think I’ll ever use them.

A nice side effect of the size of the keyboard is that your desk seems to have grown.

Mac setup

Updated BlogEngine.NET scripts

It was brought to my attention that the next release of BE will have some changes in the database scheme. I’ve compared the new script with the old one and the only changes, at the moment of this writing, are two new tables. Since the tables both use varbinary(max) they are not compatible with MS SQL 2000. I’ve changed the script to use image instead and briefly tested it. Seems to work like a charm. I’ve also looked at the code which retrieves the values and I don’t think there will be problems except hitting the maximum amount that can be stored in the image datatype, which is unlikely.

So if you check out the code from codeplex and want to use it with a MS SQL 2000 database use this file: BE_SQL2000_Dev.sql (15.07 kb) .

If you download the latest release of BE (1.3.*) you can still use the script I posted in a previous post and for your convenience I’ve added it here: BE_SQL2000_1.3.0.0.sql (14.23 kb) .

SVN on a Mac

With my ongoing adventure of getting myself to develop on my MacBook instead of my Windows machine, I was now trying to checkout the source code which I had checked in on Google. Since MonoDevelop was not working along I had to find another solution.

It appears that SVN is available via the terminal but like any lazy user I want a GUI. The Windows world is blessed with TortoiseSVN and there is a similar program for the Mac called SCPlugin. It integrates the SVN commands in the Finder but for some reason it just doesn’t want to download code hosted by Google. So for now I use SmartSVN , it’s pretty easy to use.

Vista OS X

Kids, don’t try this at home. Errr let me rephrase that, don’t try this at work.

While on my lunch break browsing the Internet I found the site of Vista OS X . Cool ! The site states that it runs on all Vista 32 bit editions with SP1, just disable the UAC and you are good to go.

One install later, mayhem strikes. I didn’t take a screen shot of the end result but believe me it did not look like Leopard or any of the pictures on the site. Oh well, probably this Vista Business edition doesn’t have some necessary component so let’s just uninstall it again. Hmmm, strange the uninstall utility says it’s removed but the dialog box asking if I’d like to uninstall still stares me in the face. On to the control panel ! Hmm, that doesn’t load anymore. Ok, a more drastic option is required, to the restore utility ! Ohw, that doesn’t show up as well. Oops! Another way to get to the system restore options is via Accessories and System Tools, that did open up the screen. The install had stated that a restore point would automatically be created, but it hadn’t. Fortunately for me another program, that I installed earlier that day had, so I was able to reverse the changes.

Lessons learned: make a restore point before installing programs that have a big impact on your system. Some voice inside my head did warn me before I clicked the install button but I chose to ignore it. It’s nice to be reminded the hard way some times ;).

Open source 1 – Benny 0

Pffff, it seems like everybody has a different 1.0 release of MonoDevelop compared to mine. Where’s the version control stuff? Where’s Gtk# under the C# tab? Screenshots and screencasts show stuff that just isn’t in my version yet they are all talking about 1.0. Where’s the documentation, guides, blogposts, anything? This is so strange, seems I’m the only one trying to get this working under Leopard.

Just had to complain about it, to be continued for sure.