Vincent Gable’s Blog

November 24, 2008

How To Put a % in an NSString/NSLog/printf

Filed under: Cocoa,MacOSX,Objective-C,Programming | , , , , , ,
― Vincent Gable on November 24, 2008

%% is turned into a single % in a call to NSLog, or -[NSString stringWithFormat:], or the printf-family of functions.

Note that %%format will become %format, even if %format usually prints an argument. For example, the code

NSLog(@"%%a will print a float in a machine-readable format, so that *scanf can read it back in from a string with no loss of precision.", 1.0f);

prints:

%a will print a float in a machine-readable format, so that *scanf can read
it back in from a string with no loss of precision.

not:

%0x1p+0 will print a float in a machine-readable format, so that *scanf can read it back in from a string with no loss of precision.

How To Space Your Code For Maximal Interoperability

Filed under: Design,Programming,Quotes,Usability | , , , , ,
― Vincent Gable on November 24, 2008

The new rule for indentation and alignment: use tabs for achieving an indentation level, spaces for character alignment within an indentation level.

Christopher Bowns (and independently Peter Hosey)

The arguments make total sense to me. Here’s hoping for better IDE support in the future. Unfortunately, (though interestingly), according to Steve Yegge, indentation is very hard:

I would have been publishing this article at least a month ago if it weren’t for indentation. No, six weeks, mininum.

See, I thought that since I had gone to all the thousands of lines of effort to produce a strongly-typed AST (abstract syntax tree) for JavaScript, it should therefore be really easy to do indentation. The AST tells me exactly what the syntax is at any given point in the buffer, so how hard could it be?

It turns out to be, oh, about fifty times harder than incremental parsing. Surprise!

Here’s a forward-looking (somewhat contrary) opinion,

Soft-wrapped code (leaving a long line long, and letting the IDE handle the spacing) also appears to be the direction that Apple are heading and they tend to drag a lot of Mac programmers along in their wake.

Matt Gallagher

November 14, 2008

Prefer copy Over retain

Filed under: Bug Bite,Cocoa,Objective-C,Programming | , ,
― Vincent Gable on November 14, 2008

(Almost) every time you use retain in Objective-C/Cocoa, you really should be using copy. Using retain can introduce some subtle bugs, and copy is faster then you think…

A Bug Waiting To Bite

The problem with using retain to “take ownership” of an object is that someone else has a pointer to the same object, and if they change it, you will be affected.

For example, let’s say you have a Person class with a straightforward setter method:
- (void) setThingsToCallTheBossToHisFace:(NSArray*)newNames {
   [thingsToCallTheBossToHisFace autorelease];
   thingsToCallTheBossToHisFace = [newNames retain];
}

And you use it to initialize a few Person objects:

NSMutableArray *appropriateNames = [NSMutableArray arrayWithObject:@"Mr. Smith"];
[anIntern setThingsToCallTheBossToHisFace:appropriateNames];

//Salaried Employees can also be a bit more informal
[appropriateNames addObject:@"Joe"];
[aSalariedEmployee setThingsToCallTheBossToHisFace:appropriateNames];

//the wife can also use terms of endearment
[appropriateNames addObject:@"Honey"];
[appropriateNames addObject:@"Darling"];
[theBossesWife setThingsToCallTheBossToHisFace:appropriateNames];


The code looks good, it compiles without error, and it has a bug in it. Because setThingsToCallTheBossToHisFace: uses retain, each Person object’s thingsToCallTheBossToHisFace field is actually pointing to the exact same NSMutableArray. So adding “darling” to the list of names the wife can use also adds it to the intern’s vocabulary.

If copy was used instead, then each Person would have their own separate list of names, insulated from changes to the temporary variable appropriateNames.

A Sneaky Bug Too

This is a particularly insidious problem in Foundation/Cocoa, because mutable objects are subclasses of immutable objects. This means every NSMutableThing is also a NSThing. So even if a method is declared to take an immutable object, if someone passes in a mutable object by accident, there will be no compile-time or run-time warnings.

Unfortunately, there isn’t a good way to enforce that a method takes an object, but not a subclass. Because Foundation makes heavy use of class clusters, it’s very difficult to figure out if you have an immutable class, or it’s mutable subclass. For example, with:
NSArray *immutableArray = [NSArray array];
NSMutableArray *mutableArray = [NSMutableArray array];

[immutableArray isKindOfClass:[NSArray class]] is YES
[immutableArray isKindOfClass:[NSMutableArray class]] is YES
[mutableArray isKindOfClass:[NSArray class]] is YES
[mutableArray isKindOfClass:[NSMutableArray class]] is YES
[mutableArray isKindOfClass:[immutableArray class]] is YES
[immutableArray isKindOfClass:[mutableArray class]] is YES

Sad, but true.

copy Is Fast!

With nearly every immutable Foundation object, copy and retain are the same thing — there is absolutely no penalty for using copy over retain! The only time you would take a performance hit using copy would be if the object actually was mutable. And then you really do want to copy it, to avoid bugs!

The only exceptions I know of are: NSDate, and NSAttributedString.

But don’t just take my word for it! Here’s the snippet of code I used to test all this:

NSMutableArray *objects = [NSMutableArray array];
//add anything that can be made with alloc/init
NSArray *classNames = [NSArray arrayWithObjects:@"NSArray", @"NSColor", @"NSData", @"NSDictionary", @"NSSet", @"NSString", nil];
for(NSString *className in classNames) {
   id obj = [[NSClassFromString(className) alloc] init];
   if(obj)
      [objects addObject:obj];
   else
      NSLog(@"WARNING: Could not instatiate an object of class %@", className);
}

//manually add objects that must be created in a unique way
[objects addObject:[[NSAttributedString alloc] initWithString:@""]];
[objects addObject:[NSDate date]];
[objects addObject:[NSNumber numberWithInt:0]];
[objects addObject:[NSValue valueWithSize:NSZeroSize]];

//test if retain and copy do the same thing
for(id obj in objects)
   if(obj != [obj copy])
      NSLog(@"copy and retain are not equvalent for %@ objects", [obj className]);

Best Practices

Get in the habit of using copy, anytime you need to set or initWith something. In general, copy is safer then retain, so always prefer it.

I believe it is best to try copy first. If an object can not be copied, you will find out about it the first time your code is executed. It will be trivial to substitute retain for copy. But it is much harder, and takes much longer, to discover that you should have been using copy instead of retain.

A program must be correct before it can be made to run faster. And we have seen there is no performance penalty for copy on most common objects. So it makes sense to try copy first, and then replace it with retain if it proves to be necessary through measurement. You will be measuring before you start “optimizing”, right? (I also suspect that if taking ownership of an object is a bottle-neck, then the right optimization is not to switch to retain, but to find a way to use a mutable object, or an object pool, to avoid the “take ownership” step altogether.)

Choose copy, unless you have a measurable justification for using retain.

UPDATE 2009-11-10: Obj-C 2.0 blocks have some peculiarities,

For this reason, if you need to return a block from a function or method, you must [[block copy] autorelease] it, not simply [[block retain] autorelease] it.

October 29, 2008

Two Help Menus

Filed under: Bug Bite,Cocoa,Interface Builder,MacOSX,Objective-C,Programming | , ,
― Vincent Gable on October 29, 2008

I ran into an issue at work where sometimes an application would have two “Help” menus, on OS X 10.5 “Leopard” (but not on OS X 10.4 “Tiger”). The problem was interacting with the UI before the application had finished enough of the AppKit-initialization process.

The application had to install a component, which involved displaying authentication dialogs and such. Because the component was necessary for the application to work correctly, I thought it would be safest to do this as early as possible. But displaying a dialog in code called from awakeFromNib ended up being the cause of the double Help Menu issue.

Waiting until applicationWillFinishLaunching: or applicationDidFinishLaunching: to interact with the user fixed the problem. (In my case, it was safe to defer the installation until then.)

I am not aware of any other issues from putting up a window “too early” … however, it seems to me that doing it is asking for trouble. The AppKit/Cocoa environment obviously isn’t 100% ready at that point. Why risk running your code with half-baked libraries if you don’t have to?

Whenever possible, I will defer “first run” behavior until applicationWillFinishLaunching: or applicationDidFinishLaunching:.

October 19, 2008

Xcode Shortcuts

Filed under: MacOSX,Programming,Tips |
― Vincent Gable on October 19, 2008

A complete list of Xcode keyboard shortcuts.

See also, my personal list of useful Mac OS X text-editing shortcuts.

October 11, 2008

An AppleScript Quine

Filed under: Announcement,Programming,Research | ,
― Vincent Gable on October 11, 2008

Here is my first quine. It’s written in AppleScript, because I wasn’t able to find, another AppleScript quine.

When run quine.applescript will make Script Editor create a new window containing the source code. It’s particularly meta if you use Script Editor (the default application) to run the quine, because it’s not just printing itself, it’s writing itself in the IDE!

Fortunately, the problems I’d originally had with Script Editor and the quine seem to have been fixed.

EDITED TO ADD: Here’s the quine’s source, but you really should download it to run it, because wordpress has a habit of subtly mucking with copied code…

set d to "on string_from_ASCII_numbers(x)
	set s to ASCII character of item 1 of x
	repeat with i from 2 to number of items in x
		set s to s & (ASCII character of item i of x)
	end repeat
end string_from_ASCII_numbers
set set_d_to to {115, 101, 116, 32, 100, 32, 116, 111, 32}
set scriptEditor to {83, 99, 114, 105, 112, 116, 32, 69, 100, 105, 116, 111, 114}
set quine to string_from_ASCII_numbers(set_d_to) & quote & d & quote & return & d
tell application string_from_ASCII_numbers(scriptEditor) to make new document with properties {contents:quine}"
on string_from_ASCII_numbers(x)
	set s to ASCII character of item 1 of x
	repeat with i from 2 to number of items in x
		set s to s & (ASCII character of item i of x)
	end repeat
end string_from_ASCII_numbers
set set_d_to to {115, 101, 116, 32, 100, 32, 116, 111, 32}
set scriptEditor to {83, 99, 114, 105, 112, 116, 32, 69, 100, 105, 116, 111, 114}
set quine to string_from_ASCII_numbers(set_d_to) & quote & d & quote & return & d
tell application string_from_ASCII_numbers(scriptEditor) to make new document with properties {contents:quine}

October 8, 2008

Drawing the floor()

Filed under: Bug Bite,Cocoa,Design,MacOSX,Objective-C,Programming | , , , , ,
― Vincent Gable on October 8, 2008

So when drawing a custom-Cocoa-control, I had an issue where an NSImage (bitmap) and an NSBezierPath (vector-shape) didn’t move in sync with each other.

Using floor() to force all pixel-coordinate to be a whole number fixed the problem. There is probably a much better solution — after-all this was the first custom-control I have ever done in Cocoa. But when a simple solution works…

UPDATED: 2009-05-25: @cocoadevcentral tweets,

NSIntegralRect() and CGRectIntegral() take a rect and return a copy which is aligned to integer coordinates. Good to avoid blurriness.

They sound like a better solution then calling floor() on each element of an image.

October 5, 2008

Restarting Your Mac OS X Cocoa Application

Filed under: Bug Bite,Cocoa,MacOSX,Objective-C,Programming,UNIX | , ,
― Vincent Gable on October 5, 2008

Restarting your own application is a tricky thing to do, because you can’t tell yourself to start up when you aren’t running. Here is one solution, use NSTask to run a very short script that you can embed right in your Objective-C code:
kill -9 YourPID
open PathToYourApp

Something to be aware of, kill -9 will immediately terminate your application, without going through the usual applicationWillTerminate: business that happens when an application quits more gracefully.

- (void) restartOurselves
{
   //$N = argv[N]
   NSString *killArg1AndOpenArg2Script = @"kill -9 $1 \n open \"$2\"";
   
   //NSTask needs its arguments to be strings
   NSString *ourPID = [NSString stringWithFormat:@"%d",
                  [[NSProcessInfo processInfo] processIdentifier]];
   
   //this will be the path to the .app bundle,
   //not the executable inside it; exactly what `open` wants
   NSString * pathToUs = [[NSBundle mainBundle] bundlePath];
   
   NSArray *shArgs = [NSArray arrayWithObjects:@"-c", // -c tells sh to execute the next argument, passing it the remaining arguments.
                killArg1AndOpenArg2Script,
                @"", //$0 path to script (ignored)
                ourPID, //$1 in restartScript
                pathToUs, //$2 in the restartScript
                nil];
   NSTask *restartTask = [NSTask launchedTaskWithLaunchPath:@"/bin/sh" arguments:shArgs];
   [restartTask waitUntilExit]; //wait for killArg1AndOpenArg2Script to finish
   NSLog(@"*** ERROR: %@ should have been terminated, but we are still running", pathToUs);
   assert(!"We should not be running!");
}

WARNING: don’t make the same mistake that I did and test restartOurselves without some kind of guard to keep your application from restarting forever. It is very difficult to kill such a beast, because whenever it starts up it takes keyboard focus away from what you are doing…. well I’m sure you get the idea.

- (BOOL) weHaveRunBefore {
   NSUserDefaults *prefs = [NSUserDefaults standardUserDefaults];
   BOOL weHaveRunBefore = [prefs boolForKey:@"weHaveRunBefore"];
   [prefs setBool:YESs forKey:@"weHaveRunBefore"];
   [prefs synchronize];
   return weHaveRunBefore;
}

October 3, 2008

Release When Ready

Filed under: Design,Programming,Usability | ,
― Vincent Gable on October 3, 2008

There are lots of people who strongly suggest that you should do your development in public. It is part of the “release early and often” concept. But I also believe that this concept is not effective in developing great ideas because it is limiting. The minute that you get real customers involved, their needs become much more pedestrian. They will yell loudly about things that may be important to their use of the product, but they will rarely yell about some new game-changing concept. In fact they will resist radical change and rethinking because it messes with their now committed workflow. And now you are comitted to supporting them. So as I see it you should strongly consider whether you have enough meat on your conceptual bone before you decide to release publicly. Because when you get users involved, it is the equivalent of putting the saw and the screwdriver down and grabbing the sand paper. There will likely be few additional big ideas after that point.

Hank Williams

September 29, 2008

Lovable Software

Filed under: Design,Programming | , , ,
― Vincent Gable on September 29, 2008

Money can’t buy you love, but love can bring you money. In software the only sustainable way to earn money is by first creating love, and then hoping that some folks want to demonstrate that love with their dollars.

…. Everything should be shareware to be tried and tested until its value is proven and the love-meter swings open the wallet. If I were to pass on some music or a piece of code I become a vector of word of mouth viral marketing, the best kind, the kind that money can’t buy.

Daniel James

« Newer PostsOlder Posts »

Powered by WordPress