Vincent Gable’s Blog

June 15, 2009

Ignoring Just One Deprecated Warning

Switching projects over to iPhone OS 3.0 means discovering that functions I’m using are deprecated. Occasionally there isn’t a totally straightforward replacement, and the best thing to do is to file a bug/TODO/note for myself, and ignore the warning until a later version, when major refactoring will be possible. But bitter experience has taught me to have Xcode treat warnings as errors1, so it’s necessary to trick the compiler into ignoring the warning for things to build.

-Wno-deprecated

The -Wno-deprecated flag tells GCC to suppress warnings about deprecated code. But adding it to an Xcode project means you won’t get useful warnings about other depreciated code.

You could file a bug telling yourself to turn that warning back on after the deprecated functionality has been updated. That should work just fine. But it feels like bad project hygiene to me.

Casting and Protocols

Type casting is a dangerous old-C technique that’s earned its infamy. But it’s undeniably fitting to use a deprecated language feature to get deprecated code to build. The basic idea is to declare a protocol that includes the method you want to suppress warnings for,

@protocol DeprecatedHack
- (void) myDeprecatedMethod;
@end

then just cast your objects so the compiler thinks they implement the protocol,

[foo myDeprecatedMethod]; //warnings
[(id<DeprecatedHack>>)foo myDeprecatedMethod]; //no warnings

Although having to declare a protocol is somewhat heavyweight, it leaves a nice artifact in the code reminding you to replace deprecated functionality.

Protocols Not Required

Sometimes just casting to id is enough. This happens if another object has a non-deprecated method with the same name.

1For experimental or prototyping projects I let warnings slide. But in the main project I always treat warnings as errors. Ignoring them in production code has never worked — warnings fester and grow on each other.

Because Objective-C is so dynamic, there are many errors that the compiler can warn you about, but can’t be totally sure are errors. For example, methods can be added to a class at runtime, so if you call -someMethodThatDoesNotExistAnywhere, the compiler will warn you that something is up, but won’t stop the build, because the necessary code could magically appear at runtime. Of course, 99% of the time, it’s me accidentally using count when I meant length, etc. What I’m really trying to say here is that treating warnings as errors is an even better idea in Objective-C.

May 19, 2009

Improving Twitter.com: Space to Work

Filed under: Design,Sample Code,Tips,Usability | , , , , ,
― Vincent Gable on May 19, 2009

The Change

Enlarge the “What are you doing” box on Twitter.com, to make compressing substantial ideas easier.

Twitter.com with a larger text-field

Motivation

I’ve been disappointed with the posting interface of every Twitter-client I’ve tried so far. Just like any writing, tweets start with a first draft. My first drafts are often longer than 140 characters. That shouldn’t be a problem; trimming the fat is part of any editing process. But most Twitter-interfaces are so downright hostile to anything longer then 140 characters that trimming a 145 letter utterance is a frustrating study in fighting my tools.

(The worst client I tried was, Blogo, which would stop you from typing and yell at you with a dialog if you dared press another key after typing 140 characters. But Twitterrific was little better; I don’t understand how something so user-unfriendly became so popular.)

Even Twitter.com doesn’t give you enough room for writing a long, but under-the-limit tweet. To see for yourself, just start typing “mmmmm”; the box will run out of room before you run out of characters. It’s downright crazy to have to scroll to see all of a tweet you are writing.

Now there’s nothing wrong with trying to prescribe a pithy style of communication. Clearly Twitter wouldn’t have worked otherwise. But punishing users for doing the “wrong” thing isn’t as effective as giving them the tools to change their behavior, to wit: space to work on shortening their writing.

The Code

This CSS code makes the direct-messaging, and “what are you doing?” text-boxes tall enough to hold 5 lines of text without scrolling. By default Twitter’s web interface only holds 2 lines of text on screen.

#dm_update_box #direct_message_form fieldset div.info textarea#text,
#status_update_box #status_update_form fieldset div.info textarea#status {
	height: 6em !important;
}

The selectors I used are pretty specific to Twitter.com, so it’s unlikely this will interfere with another site’s layout, unless it’s HTML code is nearly identical to Twitter’s.

How-To: Safari

Copy the above code into a .css file, (“CustomSafari.css” is what I called mine) then select that file in Safari -> Preferences -> Advanced -> Style sheet:
safariStyleSheet.png

After restarting Safari, Twitter’s web interface should give you room to work.

March 6, 2009

A Good Basic Computer Science Book

Filed under: Announcement,Programming,Tips | , , , ,
― Vincent Gable on March 6, 2009

In high school, I literally wore out my copy of The New Turing Omnibus: Sixty-Six Excursions in Computer Science. The graphics topics are dated, and there is no discussion about newfangled topics in computing, like the internet. But the meat of the book are timeless computer science fundamentals. It still has the best explanation of what “NP-Complete” means (page 276) that I’ve run across.

The book covers some dense territory, but is still fairly accessible. When my mother asked me, “how can a computer make a random number, if it only does what it’s told?” I pointed her to the chapter 8, “RANDOM NUMBERS: The Chaitin-Kolmogoroff Theory” (page 49). The math was a bit over her head, but she could still read the chapter, and it answered her question. I recommend it to The New Turing Omnibus, without reservation, to anyone who’s considering Computer Science.

What are your favorite introductory Computer Science books?

Patrick Thomson suggests Godel, Escher, Bach: An Eternal Golden Braid. It’s an excellent and fun introduction to the essential theory behind computer science.

Here is an excellent overview of the current state of the P=NP question.

February 11, 2009

Black on White, White on Black

Filed under: Announcement,MacOSX,Sample Code,Tips,Usability | , , , ,
― Vincent Gable on February 11, 2009

Command-Option-Control-8 will invert your screen. It’s a cool looking effect (and quite a prank if you do it to someone else’s machine), but most importantly it makes tiny-white-text-on-black webpages easier to read. Command Plus/Minus makes text larger/smaller, which helps too.

I’ve known for some time that dark text on a white background is most readable. But it until recently it was just “book learnin”. I’m young, my eyes are healthy, and I can read both color schemes just fine. I didn’t have proof I could see.

But I have trouble sleeping sometimes. A few days ago I had an “accident” with a 2L bottle of Mountain Dew and a late-night dinner of salty pizza. Look, the details of blame aren’t important here, the point is I didn’t get to sleep that night. Now, when you are very tired, it’s harder to focus your eyes — and having to focus them on a computer screen doesn’t help. About 3 in the afternoon it got downright painful to read trendy looking webpages with midnight backgrounds and petite white text. Remembering the color theory behind contrast, I gave Command-Option-Control-8 a shot, and holy shit, it worked! My screen looked like an adventure in black-lighting gone horribly wrong. But I could focus on those webpage’s text more clearly. Degraded vision from eye-fatigue gave me proof that I could see.

Now please don’t take this as anything but a biased anecdote. Trust the science, not me! But it was a neat (and painful) experience. I can see why Command-Option-Control-8 is there now. Give it a try sometime, and see if it helps for you. The most you have to lose is impressing any shoulder surfers with your computer wizardry. (Honestly though Command-Plus — make text bigger — will probably do more to enhance readability.)

Just in case you want to inver the screen programatically, this Apple Script will do the job:
tell application "System Events" to tell application processes to key code 28 using {command down, option down, control down}

January 7, 2009

Objective-C 1.0 Style: Don’t Name Your Enumerators “enumerator”!

Disclaimer

There is a better way to iterate over collections in Objective-C 1.0. You really should use it. It’s easier to write, easier to read, less prone to bugs, faster, and makes what I’m going to rant about here a non-issue, because you won’t have any NSEnumerator variables in your code.

Badly Named Problem

The standard iteration idiom in Objective-C 1.0 is:

NSEnumerator *enumerator = [collection objectEnumerator];
id element = nil;
while( nil != (element = [enumerator nextObject]) ) {
   ;//do stuff...
}

Unfortunately, I see otherwise steller programmers name their NSEnumerator variables “enumerator”. That’s always wrong, because it does not tell you what the enumerator enumerates. We already know that enumerator enumerates things, because it’s type is NSEnumerator, unless it’s name tells us more then that it’s hardly better then no name at all.

This is an especially amateurish practice because …

Naming an Enumerator Well is Easy!

Call it, the plural of the element variable. And if that won’t work you can always fall back on calling it collectionEnumerator.

For example, to fix:

NSEnumerator *enumerator = [input objectEnumerator];
NSString *path = nil;
while (path = [enumerator nextObject])

We should name enumerator paths or inputEnumerator. You might find “paths” to be too close to “path” in which case let the “plural form” of element be everyElement, giving everyPath.

These rules can be applied without much thought, but will improve the clarity of code.

Why enumerator is Worse Than i

Firstly, the practice of naming an the index in a for-loop i is not good. You can avoid it by renaming i to thingThatIsIndexedIndex.

But at least, for(int i = 0; i < collection.size(); i++), is concise; therefore better than a equally-poorly-named NSEnumerator.

Also, there is something to be said for the idiom you can just use collection[i] over declaring an extra element variable.

The Right Choice

Everyone agrees informative names are good, yet poorly named enumerators are everywhere (just browse Apple’s sample code!) Poorly named enumerators persist because nobody really uses an enumerator per se, they are just part of an iteration idiom. (So stop declaring them and iterate smarter). When was the last time you saw code that did anything with an enumerator besides [enumerator nextObject] in a while loop?

But bad habits matter. Don’t pick up the habit of naming something poorly when it’s easy to do the right thing.

December 26, 2008

Which Side To Use

Filed under: Accessibility,Tips,Usability |
― Vincent Gable on December 26, 2008

If you are ambidextrous, feel smug and ignore this.

Keep your keys, wallet, or whatever opens doors, in your weak-side pocket.

This is a bit counterintuitive. I used to keep them in my strong-side pocket for years. It’s natural to use your strong hand to unlock a door or buy a sandwich. But it causes problems when you need to open a door while carrying something awkward/heavy (say groceries, a cat, etc).

You should be carrying awkward things with your strong hand. It’s safer and easier. But when your strong-hand is full, it’s hard to get keys from your strong-side pocket. Meanwhile, keys in your weak-side pocket are still easy to employ.

I’m not especially dexterous, but in my experience, using my weak hand to unlock something hasn’t been a problem. I expected it to be harder, but honestly it hasn’t been perceptibly more difficult. Keeping keys in my weak-side pocket has been nothing but good.

Mobile-phones, pocketknives, cameras, PDAs, etc. should be in your strong-side pocket.

You should be using your strong-hand when you use them, but more importantly you (generally) don’t need to use them while carrying something. Cutting stuff while carrying a bag of groceries is a bad idea, for example.

But, anything you need to use while your strong hand is full should still live on your weak side with your keys. Phones make handy flashlights, for example.

Hold drinks with your weak hand.

I’ve been trying to train myself to do this for years, and I haven’t been able to.

The theory is that your weak hand is plenty up to the task of bringing a glass to your mouth (if it isn’t, you shouldn’t be drinking!), and it’s useful to have your strong hand free. Plus holding a cold drink makes your hand cold and wet, which surprisingly isn’t cool when you need to shake with that hand. So holding drinks in your left hand = a better first impression.

December 4, 2008

NSAssert Considered Harmful

Filed under: Bug Bite,Cocoa,MacOSX,Objective-C,Programming,Tips | , , , ,
― Vincent Gable on December 4, 2008

The NSAssert() function is unreliable, and therefore dangerous. Plain-old assert() is a better choice.

Note that #define NDEBUG disables assert(); and #define NS_BLOCK_ASSERTIONS disables NSAssert(). One kind of assert being disabled does not mean the other kind is. Nether kind of assertion is disabled by default when building in “Release” mode — you must be sure to disable them yourself. Be careful, a user will not appreciate the difference between a bug and a failed assertion — both are a crash.

assert() immediately stops your program with a SIGABORT signal. You can’t miss a failed assert(), its behavior is predictable, and it fails fast (link is a PDF).

But a failed NSAssert() behaves unpredictably. Sometimes it stops program execution, sometimes it does not and leaves the program in a strange inconsistent state. I have entirely missed NSAssert()s failing, because I did not look at the console. if(!expr) NSLog(); would have been a better choice in the those cases, because at least I would have known how it behaved.

According to Apple,

Assertion macros, such as NSAssert and NSCAssert … pass a string to an NSAssertionHandler object describing the failure. Each thread has its own NSAssertionHandler object. When invoked, an assertion handler prints an error message that includes the method and class (or function) containing the assertion and raises an NSInternalInconsistencyException.

Complicated! The complexity means it is possible to customize what happens when an NSAssert() fails. That sounds cool, but I’ve never heard of someone needing to actually do that.

If a framework catches NSInternalInconsistencyExceptions, then your program will keep right on running after a failed NSAssert(). I have had this happen to me several times. I apologize for not having taken the time to investigate what frameworks were catching what.

Apple could change what catches what with any software update.

Variability and complexity are the last things you want while debugging. There’s no reason to invite it them by using NSAssert() over assert(). Since NSAssert() is not guaranteed to stop your program, it can not be relied on to guard against data corruption, or anything worse then a predictable crash.

UPDATE 2009-06-01: You can annotate assert(), so it prints an explanation like NSAssert(), by &&ing in a string after the condition. For example assert(i < j) is a lot more useful with an explanation: assert(i < j && "unexpected cycle in graph") — on failure it prints

Assertion failed: (i < j && “unexpected cycle in graph”), function WillHalt(), file /path/to/code.m, line 30.

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.

September 27, 2008

CFShow is NSLog for Core Foundation Types

Filed under: MacOSX,Programming,Tips | , , , ,
― Vincent Gable on September 27, 2008

CFShow(coreFoundationThingy) will print out a description of coreFoundationThingy to the console. Output looks something like:

{value = w:1186.000000 h:687.000000 type = kAXValueCGSizeType}

If NSLog() is printing something out as an NSCFType, try CFShow().

September 24, 2008

XML Parsing: You’re Doing it Wrong

Filed under: Cocoa,MacOSX,Objective-C,Programming,Quotes,Sample Code,Tips | ,
― Vincent Gable on September 24, 2008

There are lots of examples of people using text searching and regular expressions to find data in webpages. These examples are doing it wrong.

NSXMLDocument and an XPath query are your friends. They really make finding elements within a webpage, RSS feed or XML documents very easy.

Matt Gallagher

I haven’t used XPath before, but after seeing Matt’s example code, I am convinced he’s right, because I’ve seen the other side of things. (I’ll let you in on a dirty little secret — right now the worst bit of the code-base I’m working on parses XML.)

    NSError *error;
    NSXMLDocument *document =
        [[NSXMLDocument alloc] initWithData:responseData options:NSXMLDocumentTidyHTML error:&error];
    [document autorelease];
    
    // Deliberately ignore the error: with most HTML it will be filled with
    // numerous "tidy" warnings.
    
    NSXMLElement *rootNode = [document rootElement];
    
    NSString *xpathQueryString =
        @"//div[@id='newtothestore']/div[@class='modulecontent']/div[@class='list_content']/ul/li/a";
    NSArray *newItemsNodes = [rootNode nodesForXPath:xpathQueryString error:&error];
    if (error)
    {
        [[NSAlert alertWithError:error] runModal];
        return;
    }

(I added [document autorelease]; to the above code, because you should always immediately balance an alloc/init with autorelease, outside of your own init methods.)

« Newer PostsOlder Posts »

Powered by WordPress