Syntonica's World   
It's a Joyous Place!
Welcome to the latest version of my world. Enjoy the words and music.
:cocoa
Cocoa: Let's Get Hammered!
Fri 19 June 2015
15:17:48

It's the programmer's choice for making pretty Mac OS X programs. Apple gives you tons of stuff for free--the development software and 1GB of documentation.

The software, a.k.a. XCode, is a very comprehensive package that includes a coding environment with all the bells and whistles a hardcore programmer could want, including a class browser, an interface builder called, strangely enough, Interface Builder, and a few dozen mini-utilities including an icon package builder and a USB probe, if you feel the need to probe your USB.

The documentation, on the other hand, leaves something to be desired. It's written by SuperGenii for Supergenii. If you are only a plain genius, then you are screwed. As well, if you are like me, you just need to see a specie of the method you want to use. It's faster and easier for my mind to grasp it and retain it. So, I will be posting a few simple posts to provide others who want a simple answer.

Good luck to all you intrepid coders and it's okay to screw up. Only you and the little hammer will know.

Oh, and if you find any mistakes, please let me know. I am human and need to be loved. syntonica at that yahoo thing dot com.
Will the Delegates from Table View please sit down?
Thu 25 June 2009
01:00:49

If you want to display a table using NSTableView, but you want to make it look all purty, with each little square different from the last, use:

-(void)tableView:(NSTableView *)aTableView willDisplayCell:(id)aCell forTableColumn:(NSTableColumn *)aTableColumn row:(int)rowIndex

Instead of delving into the cells one by one on your own, let the table present them to you with this delegate method. If you are using a data source, delegation is already set up. You only need to stuff your code into this method. You get the row as an integer, numbered from 0 on up. And you get the column, well, as a column. What more could you ask for?

From here, you can setFont:, setBackgroundColor, whatever your little hear desires. And while you are at it, don't forget about:

- (void)tableViewSelectionDidChange:(NSNotification *)aNotification

- (BOOL)tableView:aTable shouldSelectRow:(int)rowIndex


These handy delegate methods let you know when the user does something, like move to a different record. In that time, you can do stuff like save changes, populate data fields, etc.

Lesson of the Moral: don't eschew delegate methods. They make your life incredibly more simpler. Or however it goes...
What Time Is It?
Sat 20 June 2009
21:44:31

It's Morris Day, of course. Here's how to initiate and release a timer for a document window:

Put this in your init:

timer = [NSTimer scheduledTimerWithTimeInterval:300.0 target:self selector:@selector(doSometimethingTimely:) userInfo:nil repeats:YES];

The time interval is a float that can be from 0 to any number, in seconds. Here, 300.0 is 5 minutes. Target can be any class. You can use userInfo to pass stuff to the selector method and the "repeats:YES" means that after the timer fires, it will reschedule itself. If you set it to NO, it will fire once, invalidate itself and send itself to Silicon Heaven.

Create a method:

-(void)doSomethingTimely:(NSTimer *)aTimer
{
// do something timely here
}

And, to destroy the timer, it must go with the window. The window controller may not necessarily be destroyed with the window:

-(void)windowWillClose:(NSNotification *)aNote
{
[timer invalidate];
}

Who's your daddy?
Wed 17 June 2009
18:01:39

We may never know. But in Cocoa, you can find your parent.

For an NSDocument, you can get your current MyDocument instance with:

[[NSDocumentController sharedDocumentController] currentDocument]

This should get you out of most of your troubles. I found it helpful in a controller that needed to just do a single tweak. It was faster and easier than trying to pass a message.

If you are stuck in a subclass-window controller, you can get your document with:

MyDocument *document = [self document];

But if you find yourself looking for mommy or daddy from some strange place, you probably need to rethink your entire approach. Be sure to draw out your app real quick with big boxes and assign responsibilities to everybody before you even open Xcode. This will save you a metric buttload of work should you code yourself into a corner.
Warning! Warning!
Wed 17 June 2009
17:56:37

That little yellow triangle is telling you something. You have screwed up. Not a big screw up. Your app will compile and may even run. But that error is going to bite you. Hard. Maybe not now, maybe not here, but sometime. Maybe in Bangkok, walking down the street in broad daylight and, suddenly, you are dragged into an alley and that little yellow triangle steals your kidney.

Most of them only have to do with headers. Either a reference to a needed header is missing, or the method is not declared properly in the header for the rest of the Cocoa world to see. Especially if a class is complaining it can't find its own method. It happens.

So, don't ignore them. Fix them! Declare it! Shout your methods out to the world!
Where to put your value initialization stuff...
Thu 11 June 2009
14:12:55

This one is confusing for the beginner. Unlike C where you can use a define, or put it at the top or stuff it into its own file and header to be compiled in, Cocoa wants you to put it somewhere in the code... But where?

-(id)init
Use this one to set the default values for the object being created. If your class is "fortuneCookie" then you can set the text value of it to, "Help! I am trapped in a fortune cookie factory!" You will also register to listen for notifications here, if your class is nosy.

-(void)initialize
Stuff your static table data here. For example, if you are using quick integer sine tables (does anyone use those anymore?), you would define them here. You will also register your default preferences here.

-(void)awakeFromNib
When your windows, menus, and other gewgaws have been loaded, this is the place to go. Here, you can tweak your interface and make it ready for the user, hide and show fields and menu items, as needed. You can also define some data here, as well.

But where does my global data live? As well, you may ask. Cocoa seems to frown upon global variables. Don't ask me why. It's an object-oriented thing. It's better to define them as a class with accessor methods. Lots of coding amounting to little gain, but it's the Cocoa way!