Archive for the 'Cocoa' Category

Simple starter Cocoa app ideas

Wednesday, December 11th, 2013

Inspired partly by tonight’s Hour of Code, here are some index-card-sized outlines of some simple app projects you can make as someone new to Cocoa.

Text editor/word processor

  • Document-based Mac app
  • In document window: NSTextView
  • Use NSAttributedString to read/write document data
  • Document types:
    • public.plain-text
    • public.rtf
    • com.apple.rtfd
    • com.microsoft.word.doc
  • Extra credit:
    • Add a ruler (NSRulerView)

Picture viewer

  • Document-based Mac app
  • In document window: IKImageView
  • Use CGImageSource to read image (picture) & its properties
  • Document types:
    • public.png
    • public.jpeg
  • Extra credit:
    • Floating inspector panel showing the properties in an NSTableView
    • Color-correction panel (IKImageEditPanel)
    • Support folders (public.folder): display images from folder in IKImageBrowserView

PDF viewer

  • Document-based Mac app
  • In document window: PDFView
  • Use PDFDocument to read from .pdf file
  • Document types:
    • com.adobe.pdf
  • Extra credit:
    • Toolbar with zoom in/out buttons, zoom % field, page number field

How to read what I’ve been writing

Sunday, August 11th, 2013

You might have noticed that this blog of mine has gotten mighty quiet on the sort of programming-related (especially Cocoa-related) topics I historically have written about here.

There have been, and will continue to be, occasional exceptions, but, for the most part, this will remain the case for the foreseeable future.

So, where do I write about programming nowadays?

MacTech magazine.

Cover of the August 2011 issue of MacTech magazine.
The first issue with an article of mine in it.

Here’s some of what I’ve written about:

  • C and Objective-C basics
  • Introduction to NSOperationQueue
  • Uses of GCD besides dispatch_async (this one was split over two issues)
  • How Cocoa and Cocoa Touch use blocks
  • A sampling of available developer tools, both Apple and third-party (co-written with Boisy Pitre)
  • Reviews of developer documentation viewers
  • Using Quick Look
  • Practical applications of Core Image

If you want to read my previous articles, they sell old print issues for $10 each, and they sell old issues from January 2012 onward in their iPad app for $5 each.

If you want to read future articles, it’s cheaper to subscribe: iPad subscriptions are $11 (in-app) for three months, and print subscriptions are $47 for a year (or cheaper with certain coupons).

I’ve got some good stuff coming up. The immediate next thing is a two-parter on essential tools and best practices for developers. Part 1 should be in the August issue.

How to decide which ownership keyword to give a property

Sunday, July 21st, 2013
  1. If the object may come in a mutable variant (like NSString has NSMutableString), use copy, so that you don’t end up holding a mutable object that somebody mutates while you’re holding it.

  2. If you will own the object, use strong. (Optionally, leave it out, because strong is the default for objects.)

  3. If the object will own you, use weak. For example, a table view weakly references its data source and delegate, because they are very often the VC or WC that indirectly owns the table view.

  4. If the object cannot be referenced with a true weak reference, use unsafe_unretained. A select few classes*, such as NSTextView, do not support weak references. You will get an exception at run time if you try to establish a weak reference to such an object. You will have to use unsafe_unretained instead.

    The reason weak is preferable is because, if the object dies while being weakly referenced, the weak references automatically get changed to nil. That’s also the part that certain classes are allergic to. unsafe_unretained doesn’t have this feature, which is why the classes that don’t support weak can still be referenced with unsafe_unretained—but, the caveat is that if you use unsafe_unretained, you must ensure that the object will never get deallocated while you are weakly holding it—i.e., that you let go of your unsafe unretained reference before the last owner of the object lets go of that ownership.

  5. Never use assign. For objects, unsafe_unretained is synonymous and clearer (it explicitly says that it is unsafe, which it is). For non-objects (such as NSUInteger and CGFloat, leave it out—assign is the default for such values.

* The Transitioning to ARC FAQ includes a complete list of classes that do not support weak references.

(This is an expanded version of a comment I posted on Stack Overflow.)

How to create a new class in Xcode 4

Tuesday, October 16th, 2012
  1. Choose which group you want to put the class into. You must do this first, before anything else, or you will have even more work to do later.
  2. Right-click on the group or on any file reference inside it. You must create the class this way, or you will have even more work to do later.
  3. Choose “New File”. You use this same command to create classes, nibs, storyboards, plists, and files of several other types. There is no “New Class” command, and the command is called “New File” even though it often creates multiple files.
  4. Choose which platform you want to create this class for. You must choose exactly one, even if your project is cross-platform, and even if this class will be cross-platform (e.g., NSManagedObject subclass). Even if your project is single-platform, the platform for which the file(s) should be created will not be inferred from the project’s platform.
  5. (Optional) Choose which group of file templates to look in.
  6. If you performed step 5, and guessed wrong, correct yourself. (For example, OS X nibs are not among the “Resource” templates, even though they go in the Resources subfolder. You want “User Interface”.)
  7. Choose which template to use.
  8. Set the class name.
  9. Set the superclass name.
  10. Turn on “With XIB for user interface” if you’re creating a window controller or view controller.
  11. Choose where to save the file(s).
  12. Nibs created along with a WC or VC are created unlocalized (outside of a .lproj folder), so if you did step 10, select the nib and click “Make localized”.

It seems to me that there is room here for optimization.

Characters in NSString

Sunday, June 3rd, 2012

Working with Unicode in any encoding but UTF-32 (which we don’t use because, for nearly all text, it wastes tons of memory) has some pitfalls:

As UTF-8′s name implies, its code units (roughly speaking, character values) are 8 bits long. ASCII characters are all one code unit long (in UTF-8, this means that 1 ASCII character == 1 byte), but any character outside of that range must be encoded as multiple code units (multiple bytes). Thus, any single character above U+007F will end up as more than one byte in UTF-8 data.

This first observation is not limited to Emoji; it’s true of most characters in Unicode. Most characters take up more bytes in UTF-8 data than “characters” in an NSString.

As we’ll see a couple of tweets later, though, even NSString’s length can be problematic.

UTF-16 data may begin with a single specific character that is used as a byte-order mark.

(I should point out, just in case it isn’t obvious, that code units in UTF-16 are two bytes, as opposed to UTF-8′s one-byte code units. This still isn’t enough to encode any Unicode character in a single code unit, though, which will become important shortly.)

The BOM’s code point is U+FEFF. If you encode this in big-endian UTF-16 (UTF-16BE), it comes out as 0xFEFF, exactly as you’d expect. If you encode it in UTF-16LE, it comes out as 0xFFFE, which is not a character.

Thus, a BOM indicates which byte-order all of the subsequent code units should be in. If the first two bytes are 0xFFFE, you can guess that it’s 0xFEFF byte-swapped, and if that’s true, then the rest of the code units (if indeed they are UTF-16) are little-endian. The BOM isn’t considered part of the text; it’s removed in decoding.

The BOM is also used simply to promise and detect that the data is UTF-16: If you see one, whichever way it is, then the rest of the data is probably UTF-16 in one form or the other.

So it’s useful to include the BOM for data that may be saved somewhere and later retrieved by something that may need to determine its encoding.

-[NSString dataUsingEncoding:] includes the BOM, so that you can just take the data and write it out (if it is the whole data—more on that in a moment). Since the data it returns has the BOM character in it, the data’s length includes the two bytes that encode that character. -[NSString lengthOfBytesUsingEncoding:], on the other hand, counts only the bytes for the characters in the string; it does not add 2 bytes for a BOM.

A corollary to this is that if you send dataUsingEncoding: to an empty string, the data it returns will not be empty. So, are you testing whether the string you’ve just encoded is empty by testing whether the data’s length is zero? If so, your test is always succeeding/always failing.

One problem with the BOM is that it should only appear at the start of the data, which means you can’t just encode a bunch of strings using dataUsingEncoding: and then, say, write them all to a file or socket one after another, because the output will end up with BOMs (or, worse, invalid characters, namely U+FFFE) sprinkled throughout.

The naïve solution to that is to staple strings together, then encode and write out the entire agglomeration. If performance (particularly memory consumption) is an issue and you’re writing the output out piecemeal anyway, a more efficient solution would be to use getCharacters:range: or getBytes::::::: to extract raw UTF-16 code units into your own buffer.

Unicode, the character set, can hold up to 0×20000 characters. Foundation’s unichar type is 16-bit, which means it can only hold values within the range of 0×0000 to 0xFFFF.

This is a problem for all of the characters above 0xFFFF, including the Emoji characters, which are in the range from U+1F300 to U+1064F.

UTF-16 addresses this problem by means of a system called surrogates. It’s similar to what UTF-8 does for the same problem, except that the values that UTF-16 uses are within two defined ranges of actual characters.

Surrogates come in pairs. The first one is called the high surrogate, and the second is called the low surrogate. The ranges of usable characters are named accordingly.

The bomb character, 💣, encodes to UTF-16 as 0xD83D 0xDCA3.

NSString and CFString use the word “character” all over the place, but what they really mean is “UTF-16 code unit”. So the aforementioned single-character string actually contains two “characters”:

2012-06-03 13:15:45.498 test[14761:707] 0: 0xD83D
2012-06-03 13:15:45.501 test[14761:707] 1: 0xDCA3

Beware of such things when enforcing length limits. Be sure of whether you’re counting ideal characters or code units in some encoding. Also make sure you’re clear on whether a destination with a length limit (e.g., Twitter) counts up to that limit in ideal characters or in code-units in some encoding.

Also, as @schwa mentions in the same tweet, this all applies to characterAtIndex: as well (indeed, everything in NS/CFString that talks about “characters”). So, for example, [bombString characterAtIndex:0UL] will really retrieve only half of the character.

As noted above, each of these Emoji characters is encoded in UTF-16 as two code units in a surrogate pair. A surrogate pair has a high surrogate and a low surrogate.

The high surrogate identifies a range of 210 characters; the low surrogate identifies a specific character within that range. Since the poop character and the bomb character are within the same range, they have the same high surrogate—i.e., the same first “character” in their NSString/UTF-16 representations.

As the example demonstrates, just because a string contains only one ideal character doesn’t mean that characterAtIndex:0 will return 1.0 character. It may return 0.5 characters.

Greg Titus answered this one for me:

No worries about surrogate pairs or lengths greater than 1 for characters that exist in ASCII (≤ U+007f).

Recap

  • “Characters” in NS/CFString are really UTF-16 code units.
  • Some characters in Unicode—including, but by no means limited to, Emoji—are outside the range of what a single UTF-16 code unit—a single NSString “character”—can hold.
  • Therefore, do not assume that a single character is a single “character”.
  • Neither should you assume that a single character will be a single byte in UTF-8. That sounds obvious, but…
  • Both of the preceding rules can trip you up when checking against length limits (or sending text to something else that will do such a check). Make sure you know whether the limit is in ideal characters (U+whatever) or code units in some encoding, and make sure you count the appropriate unit and do so correctly.
  • Those rules also have a way of tripping you up whenever you extract a single “character” at a time from a string. You should probably only do this when looking for known ASCII characters (e.g., for parsing purposes), and even then, please consider using NSScanner or NSRegularExpression instead.

On the API design of CGBitmapContextCreate

Friday, June 1st, 2012

Let’s review the prototype of the CGBitmapContextCreate function:

CGContextRef CGBitmapContextCreate (
 void *data,
 size_t width,
 size_t height,
 size_t bitsPerComponent,
 size_t bytesPerRow,
 CGColorSpaceRef colorspace,
 CGBitmapInfo bitmapInfo
);

The arguments:

  • data may be a pointer to pixels. If you pass NULL, the context will create its own buffer and free that buffer itself later. If you pass your own buffer, the context will not free it; it remains your buffer that you must free after you release the context, hopefully for the last time.
  • width and height are what their names say they are, in pixels.
  • bitsPerComponent is the size of each color component and the alpha component (if there is an alpha component), in bits. For 32-bit RGBA or ARGB, this would be 8 (32÷4).
  • bytesPerRow is as its name says. This is sometimes called the “stride”.
  • colorspace is a CGColorSpace object that specifies what color space the pixels are in. Most importantly, it dictates how many color components there are per pixel: An RGB color space has three, CMYK has four, white or black has one. This doesn’t include alpha, which is specified separately, in the next argument.
  • bitmapInfo is a bit mask that specifies, among other things, whether components should be floating-point (default is unsigned integer), whether there is alpha, and whether color components should be premultiplied by alpha.

The most immediate problem with this function is that there are so damn many arguments. This is especially bad in a C function, because it’s easy to lose track of what each value specifies, especially when so many of them are numbers. Suppose you want to make an 8-by-8-pixel grayscale context:

CGContextRef myContext = CGBitmapContextCreate(NULL, 8, 8, 8, 8, myGrayColorSpace, kCGImageAlphaNone);

Now, without looking at the prototype or the list, which argument is bitsPerComponent, which is bytesPerRow, and which are width and height?

Objective-C’s names-and-values message syntax can help with this, as we can see in the similar API (for a different purpose) in NSBitmapImageRep:

NSBitmapImageRep *bir = [[NSBitmapImageRep alloc]
    initWithBitmapDataPlanes:NULL
                  pixelsWide:8
                  pixelsHigh:8
               bitsPerSample:8
             samplesPerPixel:4
                    hasAlpha:YES
                    isPlanar:NO
              colorSpaceName:NSCalibratedRGBColorSpace
                 bytesPerRow:8
                bitsPerPixel:8*4];

But this has other problems, notably the redundant specification of bitsPerPixel and samplesPerPixel. With that and the isPlanar argument, this method takes even more arguments than CGBitmapContextCreate. More importantly, it doesn’t solve the greater problems that I’m writing this post to talk about.

EDIT: Uli Kusterer points out that bitsPerPixel is not redundant if you want to have more bits not in a component than just enough to pad out to a byte. That’s a valid (if probably unusual) use case for NSBitmapImageRep, so I withdraw calling that argument redundant.

I’m going to use the example of both of these APIs, but mainly CGBitmapContextCreate, to talk about a few principles of API design.

The first is that it should not be possible for an object to exist in an unusable state. From the moment a freshly-created object is returned to you, you should be able to use it without it blowing up in your face.

From this principle follows a corollary: Everything an object needs in order to function, it should require when you instantiate it. Otherwise, the object would exist without the needed information—and thereby be unable to function—until you provide it.

It might seem that these APIs are as long as they are in order to uphold that principle. After all, a bitmap context needs to have someplace to put its pixels, right? (In fact, CGBitmapContextCreate‘s buffer argument was required until Snow Leopard and iOS 4.) It needs to know what format the pixels should be in, right?

Now for the second principle: Any information that an object does not need in order to function should be omitted from initialization and provided afterward. In Objective-C, the most common means of this post hoc specification are readwrite properties and delegate messages. Generally, for anything that could be specified in the initializer, the post hoc way to specify it would be via a property.

We’d like to invoke the second principle and move things out of the initializer, but that would seem to conflict with the first principle: What can we move that the context does not require?

The resolution is in a third principle—one that is not specific to APIs, but applies to all interfaces, including user interfaces: An interface should have reasonable defaults for as many parameters as it can—it should only require the user to provide values for parameters for which no default can be reasonably chosen in advance.

With that in mind, let’s look at some of CGBitmapContextCreate‘s arguments and see how we might apply the reasonable-defaults principle to simplify it:

  • bitsPerComponent, bitmapInfo, and colorspace: Most commonly, the caller will want 8-bit RGBA or ARGB, often with the goal of making sure it can be used on the graphics card (either by way of a CG- or CALayer or by passing the pixels directly to OpenGL). That’s a reasonable default, so these three can be eliminated.

    We could make them properties, but there’s an alternative: We could dynamite bitmapInfo and merge some of its values with bitsPerComponent in the form of several pixel-format constants. You’ve seen this approach before in QuickTime and a few other APIs. CGBitmapContext only supports a specified few pixel formats anyway, so this simply makes it impossible to construct impossible requests—another good interface principle.

  • bytesPerRow: Redundant. The number of bytes per row follows from the pixel format and the width in pixels; indeed, CGBitmapContextCreate computes this internally anyway and throws a fit if you guessed a number it wasn’t thinking of. Better to cut it and let CGBitmapContextCreate infer it.

    Making you compute a value for bytesPerRow does provide an important safety check, which I’ll address shortly.

    EDIT: Alastair Houghton points out another case for keeping bytesPerRow. This doesn’t apply to CGBitmapContextCreate, which rejects any value that doesn’t follow from the pixel format and width in pixels, but could be valid for NSBitmapImageRep and CGImage.

  • data (the buffer): Since Snow Leopard and iOS 4, the context will create its own buffer if you don’t provide one. That makes it explicitly optional, which means it is not required.

The only arguments that are truly required are the width and height, which tell the context how many pixels it should allocate its initial buffer for in the given (or default) pixel format.

In fact, if we take the above idea of replacing three of the arguments with a single set of pixel-format constants, then we don’t actually need to make any of the properties readwrite—there isn’t any reason why the owner of the context should be changing the pixel format on the fly. You might want to change the width or height, but CGBitmapContext doesn’t support that and we’re trying to simplify, not add features.

So, what problems do the current APIs solve, what problems do they raise, and how would we address all of both problems?

  • Specifying the pixel format (bitsPerComponent, colorspace, bitmapInfo) up front saves the context having to reallocate the buffer to accommodate any pixel-size changes.

    If we simply removed the pixel format arguments from the initializer and made them readwrite properties (or a property), then the context would have to reallocate the buffer when we change the pixel format from the default (ARGB or something similar) to something else (e.g., grayscale).

    The immediate solution to that would be for the context to allocate its buffer lazily the first time you draw into it, but that would mean every attempt to draw into the context would hit that “have we created our buffer yet” check.

    A better solution would be to follow the above idea of condensing the specification of the pixel format down to a single constant; then, we could have a designated initializer that would take a pixel-format value, and a shorter initializer for the default case that calls the DI with the default pixel-format value.

  • Specifying the buffer as a plain pointer (or pointer to one or more other pointers) requires the dimensions of the buffer to be specified separately.

    It’s a mystery to me why CGBitmapContextCreate doesn’t take a CFMutableData and NSBitmapImageRep’s initializers don’t take an NSMutableData. With these, the length in bytes would be associated with the buffer, enabling the context/rep to check that the length makes sense with the desired (or default) pixel format. This would be better than the current check in two ways: First, the current check only checks bytesPerRow, ignoring the desired height; second and more importantly, the current check only checks the value you gave for bytesPerRow—it can’t check the actual length of the buffer you provided.

    (From that, you can derive a bit of guidance for using the current API: If you pass your own buffer, you should use the value you computed for bytesPerRow in computing the length of your buffer. Otherwise, you risk using one stride value in allocating the buffer and telling a different one to CGBitmapContextCreate.)

  • Requiring (or even enabling) the buffer to be provided by the caller is redundant when the API has all the information it needs to allocate it itself.

    This was especially bad when the buffer was required. Now that CGBitmapContext can create the buffer itself, even having that optional input is unnecessary. We can cut this out entirely and have the context always create (and eventually destroy) its own buffer.

  • The caller must currently choose values for parameters that are not important to the caller.

    The current API makes you precisely describe everything about the context’s pixels.

    WHY? One of the central design aspects of Quartz is that you never work with pixels! It handles file input for you! It handles rendering to the screen for you! It handles file output for you! Core Image handles filtering for you! You never touch pixels directly if you can help it!

    99% of the time, there is no reason why you should care what format the pixels are in. The exact pixel format should be left to the implementation—which knows exactly what format would be best for, say, transfer to the graphics card—except in the tiny percentage of cases where you might actually want to handle pixels yourself.

With all of this in mind, here’s my ideal API for creating a bitmap context:

typedef enum
#if __has_feature(objc_fixed_enum)
: NSUInteger
#endif
{
    //Formats that specify only a color space, leaving pixel format to the implementation.
    PRHBitmapContextPixelFormatDefaultRGBWithAlpha,
    PRHBitmapContextPixelFormatDefaultRGBNoAlpha,
    PRHBitmapContextPixelFormatDefaultWhiteWithAlpha,
    PRHBitmapContextPixelFormatDefaultWhiteNoAlpha,
    PRHBitmapContextPixelFormatDefaultCMYK,
    PRHBitmapContextPixelFormatDefaultMask,

    PRHBitmapContextPixelFormatARGB8888 = 0x100,
    PRHBitmapContextPixelFormatRGBA8888,
    PRHBitmapContextPixelFormatARGBFFFF, //128 bits per pixel, floating-point
    PRHBitmapContextPixelFormatRGBAFFFF,
    PRHBitmapContextPixelFormatWhite8, //8 bpc, gray color space, alpha-none
    PRHBitmapContextPixelFormatWhiteF, //Floating-point, gray color space, alpha-none
    PRHBitmapContextPixelFormatMask8, //8 bpc, null color space, alpha-only
    PRHBitmapContextPixelFormatCMYK8888, //8 bpc, CMYK color space, alpha-none
    PRHBitmapContextPixelFormatCMYKFFFF, //Floating-point, CMYK color space, alpha-none

    //Imagine here any other CGBitmapContext-supported pixel formats that you might need.
} PRHBitmapContextPixelFormat;

@interface PRHBitmapContext: NSObject

- (id) initWithWidth:(NSUInteger)width
    height:(NSUInteger)height;
- (id) initWithWidth:(NSUInteger)width
    height:(NSUInteger)height
    pixelFormat:(PRHBitmapContextPixelFormat)format;

//There may be an initializer more like CGBitmapContextCreate/NSBitmapImageRep's (taking individual pixel-format values such as color space and bits-per-component), but only privately, to be used by the public DI.

//Mutable so that an asynchronous loader can append to it. Probably more useful in an NSBitmapImageRep analogue than a CGBitmapContext analogue.
@property(readonly) NSMutableData *pixelData;

@property(readonly) NSColorSpace *colorSpace;
@property(readonly) bool hasAlpha;
@property(readonly, getter=isFloatingPoint) bool floatingPoint;
@property(readonly) NSUInteger bitsPerComponent;

- (CGImageRef) quartzImage;
//scaleFactor by default matches that of the main-menu (Mac)/built-in (iOS) screen; if it's not 1, the size (in points) of the image will be the pixel size of the quartzImage divided by the scaleFactor.
#if TARGET_OS_MAC
- (NSImage *) image;
- (NSImage *) imageWithScaleFactor:(CGFloat)scale;
#elif TARGET_OS_IPHONE
- (UIImage *) image;
- (UIImage *) imageWithScaleFactor:(CGFloat)scale;
#endif

@end

With the current interface, creating a context generally looks like this:

size_t bitsPerComponent = 8;
size_t bytesPerComponent = bitsPerComponent / 8;
bool hasAlpha = true;
size_t bytesPerRow = (CGColorSpaceGetNumberOfComponents(myColorSpace) + hasAlpha) * bytesPerComponent * width;
CGContextRef context = CGBitmapContextCreate(NULL, width, height, bitsPerComponent, bytesPerRow, myColorSpace, myBitmapInfo);

With an interface such as I’ve described, creating a context would look like this:

PRHBitmapContext *context = [[PRHBitmapContext alloc] initWithWidth:width height:height];

Or this:

PRHBitmapContext *grayscaleContext = [[PRHBitmapContext alloc] initWithWidth:width height:height pixelFormat:PRHBitmapContextPixelFormatWhite8];

Much faster

Saturday, October 15th, 2011

I’ve just pushed a couple of improvements to my ISO 8601 date formatter. Previously, it was pathetically slow compared to C standard library parsing and unparsing; now, it is faster.

Timing ISO8601DateFormatter
Time taken: 0.130194 seconds
Number of dates and strings computed: 10000 each
Time taken per date: 0.000013 seconds
Timing C standard library parsing and unparsing
Time taken: 0.192645 seconds
Number of dates and strings computed: 10000 each
Time taken per date: 0.000019 seconds

You’ll want at least revision [61d2959c6921] or later.

My thanks to Sam Soffes and Rudy Richter for alerting me to the speed problem.

Edited at 16:35. Previously, it was almost as fast as C stdlib. Now it is faster.

Conferences 2011

Monday, September 12th, 2011

It’s that time again! Just like last year, there are a bunch of different conferences going on; unlike last year, I’m not going to even attempt to list all of them.

The two that I have a reason to mention are:

  • Voices That Matter. This time it’s in Boston, November 12 and 13. Their early bird pricing is still on through September; I’ll let their site tell you more. As I do whenever I mention it here, I have a coupon code for it, which is BSTBLOG. As usual, due to time and expense constraints, I won’t be attending this one.
  • MacTech Conference. I’m presenting again—same topic as last year, how to recognize, find, and fix bugs in Cocoa applications, but this time it’s the Xcode 4 edition. The early bird period has ended, but you can get the same $500 off by signing up through this referral link. The time and place is November 2, 3, and 4 in Universal City, California.

Last year at the MacTech Conference, I brought with me some of my useful Cocoa links business card. I’ll be doing that again this year, so if you attend the MacTech Conference, feel free to ask me for one.

I hope to see you at the MacTech Conference!

How to make the Help key do something useful

Tuesday, June 14th, 2011

If you want to see the techniques explored in this blog post in a working application, download ContextHelpTest and/or its source code.

If you’ve used Mac OS X with an Apple extended keyboard of some sort, chances are you’ve seen this:

The Help cursor, a question mark.

That’s the cursor that comes up when you press the Help key. And every time, if you click while that cursor is up, you get a beep and the cursor changes back. (If you press a key instead, the cursor changes back and the keystroke goes through, which often will still get you a beep.)

So most of us probably forget the Help key exists, and curse it when we are reminded of it by pressing it by accident.

But what does it do, really? What is it meant to do?

Every responder can respond to a message called helpRequested:. The default implementation is to ask the help manager for the attributed string set as help for itself. If you’ve never set any help for it, then the help manager will return nil, and the default helpRequested: implementation will pass the message on to the next responder. If you have set help for the responder, then it will tell the help manager to show that help.

So here’s what you need to do:

  • To associate a help text with a view or other object, send the help manager a setContextHelp:forObject: message, passing the help attributed string and the view/other object. When the object is a view, this is all you need to do for Help-clicking on the view to do the right thing.
  • To programmatically show context help for an object, use showContextHelpForObject:locationHint:. Note that you pass the object to look up, not the help text, here. The location hint is where the user might have Help-clicked to bring up the context help.
  • To make your custom view able to show context help for things it draws within itself, override helpRequested:, find what the user clicked on, lazily set the context help for the clicked object (if appropriate), and look it up. If the user didn’t click on anything or you don’t have any help worth providing for it, pass the message on to super.
  • To programmatically enter Help-key mode, send the activateContextHelpMode: action message to the application object. If you want to make a control or menu item in a nib do this, connect it to that action on the First Responder.

Note that the help manager does not retain your definable objects. If an object that has help set for it is deallocated, that will cause a crash later on. Therefore, when setting context help for a view, the view itself should do so within its initWithFrame: (or other designated initializer) and initWithCoder: methods, and remove itself from context help in dealloc. (I don’t know how this goes under GC or ARC.)

You might also have noticed that I’m not simply saying “view” or “responder”. The help manager does not restrict you to setting help for responders or views; any object can have context help set for it. This includes model objects. This is very, very useful for implementing a view that does selective context help on things within it: You set context help for each model object, and the view tells the help manager to show help for the clicked model object.

When setting context help for a non-responder, the controller that owns it should do that, and should remove the object from context help before releasing the ownership.

So, here’s a test app.

Context help works the usual way on the word-count field:

Help-clicking on the word-count field shows a tooltip-looking popover that shows the context help associated with the field.

The text view is a subclass of NSTextView that implements helpRequested: by determining what word the user clicked on (by sending itself characterIndexForInsertionAtPoint: and then using a CFStringTokenizer to walk through its words) and then looking that word up in the dictionary.

Help-clicking on the word-count field shows a tooltip-looking popover that shows the dictionary definition associated with the clicked-on word.

Naturally, since not everybody has a Help key anymore, I provided an alternative.

The Edit menu contains a Define menu item, with the keyboard shortcut of ctrl-slash.

I look forward to seeing what uses you come up with in your apps for this.

The application delegate and the new singletons

Friday, March 18th, 2011

Here is a global variable:

Wizard *gWizard;

I’ll call this a zeroth-order global, on the premise that I need to talk to exactly zero objects (including classes) to gain access to this object.

Next, let’s look at a singleton:

[Wizard sharedWizard]; //hope he's not busy

I’ll call this a first-order global, as we need to ask the class for it (1 step) to gain access to it.

Now, here’s a second-order global:

MyAppDelegate *appDelegate = [[UIApplication sharedApplication] delegate];

(I use UIApplication here because I see this most frequently in Cocoa Touch code, but the pattern applies equally to Cocoa.)

And here’s a third-order global:

Wizard *wizard = [appDelegate wizard];

I need to (1) ask the UIApplication class for the application object, (2) ask that for its delegate, and (3) ask that for the wizard. (Assume here that wizard is a property, not a factory method that creates Wizards on the fly.)

None of these is any less global. If I can get to it from anywhere in the program without knowing about it directly, it is global.

Therefore, all the problems of globals apply:

  • What if two threads want to use the same Wizard?
  • What if the Wizard has a delegate of its own, and I have two objects that want to be its delegate?
  • What if the Wizard keeps internal state that may be corrupted by multiple objects trying to use it? (Nothing should have to worry about this outside of the Wizard itself.)

Your application’s objects form a graph. It should not be a complex one like this:

At the top, the application object. From it, its delegate. From it, your controller objects and a wizard. From each controller object, a path (colored in red) back to the delegate and then to the wizard.

Whenever you have paths bouncing around off of other objects like that, that’s a problem. The red arrows in the problem graph show where you violate the Law of Demeter.

Your object graph should, instead, be straightforward:

At the top, the application object. From it, its delegate. From it, your controller objects. From each one, a wizard.

Note that each of your controllers should own—or, if you prefer, hire—a Wizard all to itself. This eliminates contention between objects and reduces the likelihood of contention between threads (assuming each of the owning objects is supposed to only work on a single thread and not juggle multiple threads).

If contention is not a problem and you have a good reason why there should be only one Wizard, such as memory pressure or union regulations, then use a singleton. But use a real singleton, and only when necessary, and beware of singletons in disguise.

The new and improved Cocoa links card

Tuesday, March 15th, 2011

I’ve previously mentioned that I made a business card full of useful Cocoa and Cocoa Touch links to give to new Cocoa and Cocoa Touch programmers at events such as CocoaHeads.

Today, I have updated it and given it a web page. 1-up and 10-up (US Letter) PDFs are available there, as well as the full list of unshortened links.

I encourage you to print out the 10-up onto perforated business card paper, or have it professionally printed (keeping in mind that you probably won’t need 1000 of them), and make the cards available to novice Cocoa and Cocoa Touch programmers at the CocoaHeads or NSCoderNight events you attend. Just please be sure to print both sides, since my credit link is on the back.

Apple documentation search that works

Sunday, March 6th, 2011

You’ve probably tried searching Apple’s developer documentation like this:

The filter field on the ADC documentation library navigation page.

Edit: That’s the filter field, which is not what this post is about. The filter sucks. This isn’t just an easy way to use the filter field; it’s an entirely different solution. Read on.

You’ve probably been searching it like this:

Google.

(And yes, I know about site:developer.apple.com. That often isn’t much better than without it. Again, read on.)

There is a better way.

Better than that: A best way.

Setup

First, you must use Google Chrome or OmniWeb.

Go to your list of custom searches. In Chrome, open the Preferences and click on Manage:

Screenshot with arrow pointing to the Manage button.

In OmniWeb, open the Preferences and click on Shortcuts:

Screenshot of OmniWeb's Shortcuts pane.

Then add one or both of these searches:

For the Mac

Chrome OmniWeb
Name ADC Mac OS X Library
Keyword adcmac adcmac@
URL http://developer.apple.com/library/mac/search/?q=%s http://developer.apple.com/library/mac/search/?q=%@

For iOS

Chrome OmniWeb
Name ADC iOS Library
Keyword adcios adcios@
URL http://developer.apple.com/library/ios/search/?q=%s http://developer.apple.com/library/ios/search/?q=%@

Result

Notice how the results page gives you both guides and references at once, even giving specific-chapter links when relevant. You even get relevant technotes and Q&As. No wild goose chases, no PDF mines, no third-party old backup copies, no having to scroll past six hits of mailing-list threads and Stack Overflow questions. You get the docs, the right docs, and nothing but the docs.

For this specific purpose, you now have something better than Google.

PSA: Removing objects from arrays

Saturday, January 1st, 2011
  1. You create an NSMutableArray.
  2. You add the same object to it twice.
  3. You send the array one removeObjectIdenticalTo: message, passing the object you added.

What is the count of the array?

If you said 1, you’re wrong.

Worse, you might think the opposite of addObject: is removeObject: (especially if you’d never heard of the …IdenticalTo: version), but that’s even more wrong: removeObject: finds the object(s) to remove by testing equality (sending them isEqual: messages), not simply searching for the object you passed in.* That means it may remove objects that aren’t the object you passed in, but are equal to it. So, unless you really do want to remove any objects equal to the one you have, you should prefer removeObjectIdenticalTo:.

But that still removes the object entirely from the array, regardless of how many times it’s there. Unless you really want that, you more probably want this:

NSUInteger idx = [myArray indexOfObjectIdenticalTo:obj];
[myArray removeObjectAtIndex:idx];

And even then, that will remove the object from the first place you added it in at, not the last, so if you specifically need to remove it from the last place you added it (LIFO instead of FIFO), then you need to enumerate the array backwards, counting an index down as you go, remove the object at the index upon finding the object, and finally break out of the loop.

To make that easy and avert the otherwise high likelihood of off-by-one errors in many independent implementations, here’s a category you can add to your projects. Use anywhere you need the opposite of -[NSMutableArray addObject:].

* This doesn’t matter for sets, since it dupe-checks every object coming in based on equality anyway. With a set, removing the equal object and removing the same object are the same thing, which is why NSMutableSet doesn’t have removeObjectIdenticalTo:. Not so for arrays, which is why NSMutableArray does.

Helping people

Saturday, November 6th, 2010

There’s a recurring theme I keep seeing in questions on Stack Overflow.

I’ve said those words a few times now. I’ve said it twice at my recognizing-Cocoa-bugs presentation, which I’ve given at one CocoaHeads and at the MacTech Conference (just concluded yesterday). I’ve also said it a few other times at CocoaHeads, usually in preface to explaining something that’s both germane to the current conversation and the common source of confusion in the questions I’m then referring to. Plus, I’ve said it a couple of times in posts here.

In the concluding session of the conference, Edward Marczak, MacTech’s executive editor, cited a number of tweets related to various cool things that happened in the past few days. One of them was from me, inviting attendees to flag me down for one of my useful-Cocoa-links cards, which I’d previously offered up to audience members in my session. He told the audience how cool he thought it was that I’d thought ahead and made those cards.

The reason I’d made those cards was because I’d identified a pattern. In my answers on Stack Overflow, I often cite one or more of a few key documents:

or tell the questioner to listen to or turn on some warning or other and link to my warnings blog post as part of that.

My introductory document for Cocoa and Cocoa Touch, in its own introduction, identifies a similar genesis: Everything on that page is something I’d had to explain to multiple people on Stack Overflow, so I decided to put it all in one place for easy linking (by me) and easy reading (by new Cocoa or Cocoa Touch programmers). That document is also among the links on the card.

Each of the things I got praised for in that concluding session, and thanked for (besides Growl, which is mostly a lot of other people’s work) outside of sessions, I made because I’d identified a need by spotting a pattern.

There’s no reason you can’t do this, too. What have you done multiple times lately? Especially, what have you done or made or found for other people multiple times?

Somewhere on Eric Raymond’s site, there’s an explanation of the difference between newbies and wizards. It’s not that the wizards know all that much more than the newbies (though they often do have a stronger/deeper conceptual understanding); asked for the name of a function, say, the wizard will probably not know it exactly (unless it is very simple, such as CFRetain, or one they use very frequently, such as CFRetain).

The difference between them is that the wizard knows where to look stuff up. I sometimes refer to this as “swapping things in”, the analogy being virtual memory: I remember very little at any given moment, precisely because I know where I can get it from when I need to get it back into my mental working set.

The wizard knows how to help themself.

How can you enable people to help themselves?


Here’s that card, if you want one.

Ship-It Saturday: PRHEmptySingleton repository

Saturday, September 4th, 2010

The singleton-done-right example from my article on the subject is now in a Mercurial repository on Bitbucket. The repository includes not only the class (which I’ve put in the public domain), but also a test suite for some of the test cases listed in the post.

There are some adventurous testing techniques at work here.

First, since we don’t want multiple test runs to use the same singleton instance, the test cases actually run in subprocesses. Each test method is prefaced with this code:

if (!isInSubprocess) {
    [self runTestInSubprocess:_cmd];
    return;
}

That method calls fork.

In the child process, the test case sets isInSubprocess to YES, then tells itself to perform that selector; this gets execution back to the test method, which checks the variable again, finds that it’s true this time, and continues on with the test.

The parent process calls waitpid and checks the result; if the child failed, the parent propagates the failure. If the child crashed (got a signal), the parent raises the same signal; if the child simply exited abnormally, then the parent exits with the same status.

Second, there’s test case #6:

  • If [super init] returns a different object, alloc/init won’t break.

That one is hard to test, because PRHEmptySingleton’s superclass is NSObject, and -[NSObject init] doesn’t return a different object. (Not in any version of Foundation I’ve ever encountered, anyway.)

So, the first step is to create an intermediate class that does return a different object. But that doesn’t help as long as PRHEmptySingleton is still a direct subclass of NSObject.

The simple solution would be to just change PRHEmptySingleton’s superclass, but that reduces the purity of the testing: A test should be able to work without modifying the code under test, and any changes to the code under test should be permanent changes that aren’t only to enable the test; you should be able to explain the changes as if the test case did not exist.

So what I did was to import everything in my prefix header, even more than I usually do, and then import my intermediate class’s header, and then use the preprocessor to ensure that any direct subclasses of NSObject declared elsewhere are declared as subclasses of the intermediate class. Thus, the prefix header causes PRHEmptySingleton to be a subclass of the intermediate class with no changes to PRHEmptySingleton’s header. It’s a bit of a hack, and doing this sort of thing could potentially cause problems in a larger program or test suite, but in this context, it works.

With that, five of the six test cases in the original post are now covered (I’m not sure how to cover #3 without changing PRHEmptySingleton.[hm]), and the code is under version control, so you can subscribe to and track changes.

Please use singletons responsibly.

Dueling conferences

Thursday, August 5th, 2010

There are two four five six development conferences coming up this fall:

Here’s an iCalendar file of these events.

The cheapest conference is 360|MacDev, at $300 ($200 with early-bird pricing). The second-cheapest is Voices That Matter, costing $395 with the coupon and early-bird pricing. SecondConf is a little more expensive, at $449, and 360|iDev is a little more expensive than that, at $599. The iPhone/iPad DevCon is hard to compare; it’s either the most expensive at $1395 ($1065 with early-bird pricing) or the least expensive at free, depending on which kind of ticket you get. Ignoring the DevCon, MacTech’s conference is the most expensive at $899, but is also the broadest, consisting of development (both Mac and iOS) plus an IT track.

I will not be at the Voices That Matter conference, SecondConf, the DevCon, or 360|iDev (I’m still not an iPhone/iPad developer), nor 360|MacDev (too far), but I will be at the MacTech conference. In fact, I’ll be presenting.

My presentation, intended for new Cocoa and Cocoa Touch developers, will be a demonstration of what various kinds of bugs look like in Cocoa and Cocoa Touch applications, along with how to hunt down and fix those bugs.

Whichever conference you go to, have fun, and if you’re coming to the MacTech conference, I hope to meet you there.

UPDATE 2010-09-10: Added SecondConf and iPhone/iPad DevCon (thanks to Jeff in the comments for telling me about the latter).

UPDATE 2010-09-11: Added 360|iDev after its organizers followed me on Twitter. Five conferences in seven weeks—maybe some of you could get together and consolidate next year? And again a few minutes later: And 360|MacDev, making six in 11 weeks.

Capture Cursor

Saturday, March 13th, 2010

Most people don’t know how to get the cursor that’s currently on the screen—a useful ability, especially if you’re writing screenshot or screen-recording software. I’ve written an app that demonstrates the technique, or at least tries to.

It’s a bit flaky. The API it uses, IOFramebuffer, doesn’t tell me how many frames there are or what format they’re in, so the app assumes ARGB in native byte-order and doesn’t worry about frames. This gives wrong results more of the time than I like.

I’ve filed a request for a higher-level API, which would make the task much easier and the app much shorter.

I’ve posted a build in the repository’s downloads area, in case you’d like to see it in action. If you want to build it yourself, you’ll need to download SGHotKeysLib and put the source where the Capture Cursor Xcode project expects it to be.

UPDATE 2010-08-28: I’ve pushed a change, [9cbec7dd5169], that deletes the IOFramebuffer-based category method and uses Snow Leopard’s new, far more reliable [NSCursor currentSystemCursor] instead. I suggest you do the same.

Easy main-thread performing category

Saturday, February 13th, 2010

Anyone who’s ever had to perform a message on the main thread knows how ugly the code can be:

[obj performSelectorOnMainThread:@selector(receiveAnswer:)
                      withObject:[NSNumber numberWithUnsignedInteger:42]
                   waitUntilDone:NO];

I’ve written a category that changes the above code to something much simpler:

[[obj performOnMainThread_PRH] receiveAnswer:42];

Notice that not only is the code much easier to read and to write, but you no longer need to box and unbox primitive values.

You can get the code, under a BSD license, from the higher-order main-thread perform repository.

Back when I originally mentioned my creation of the category on Twitter, Dave Dribin replied that he had already written one of his own. His is part of his DDFoundation framework, and requires DDInvocationGrabber (a fork of Jonathan Wight‘s CInvocationGrabber), also part of that framework.

My category requires nothing but Cocoa and is not part of a larger framework. That said, it’s interesting to read in his code how the functionality of the Invocation Grabber makes his implementation nothing but a thin wrapper around it. (Also, his version lets you say waitUntilDone:YES.)

An introduction to Cocoa and Cocoa Touch

Wednesday, February 3rd, 2010

If you know someone who’s recently taken up programming the Mac or the iPhone (or both), please give them one (or both) of these links:

As a frequent answerer of questions on Stack Overflow, I see certain patterns—not just frequently-asked questions, but also frequently-unasked questions: Things that are biting the questioner that they don’t know about.

Sometimes they’re thinking about things the wrong way (e.g., using property list objects where they should have a model). Sometimes there is a route to a solution (“my app is slow” “run Instruments”), but they don’t know about that route. Often, they’ll use wrong terms that are right on another platform (like “member variable”), like a speaker using their native language’s pronunciation rules when speaking a foreign one.

To help people over these speed bumps, I’ve composed an introduction for new Cocoa and Cocoa Touch programmers. (Both of the above links redirect to it.)

If any part of it doesn’t help them (i.e., is unclear or wrong), I’d appreciate it if you’d let me know, either here or by email.

Reunification

Tuesday, February 2nd, 2010

A common question from people new to Objective-C is “why do I have to separately alloc and init? Why can’t I just call one thing and get a fully initialized object?”.

It’s certainly not how other environments do it. Usually, you call one function or class method, and you get an object. Cocoa makes you send two messages: one to the class, then another to the fresh, uninitialized instance you got back. What does Cocoa know that those other environments don’t?

There are two reasons why alloc and init are separate:

  • “NSResponder”* says that sometimes, NeXT wanted to initialize the same object multiple times.

    This is interesting, but horrifying to modern readers. Practically all init methods I’ve seen do not handle the case of initializing the already-initialized; they blindly assign newly created/retained objects to the ivars without checking for existing objects there.

    A bigger problem is when the init method releases the receiver and returns some other object; in the second message, the “other” object may in fact be the receiver (returned from the first message), so [self release] this time would be killing off an object that should stay alive. On the other hand, retaining the object before re-initializing it will create a leak if the object doesn’t release itself. Unpredictable behavior is bad.

  • On the same Stack Overflow question, Darren points out that alloc is shorthand for allocWithZone:; if allocation and initialization were merged in Cocoa, then, to maintain the same functionality, every initializer would need to take a zone parameter, and optionally come in a flavor without one. You can imagine how a proliferation of initializers would ensue.

    This is essentially what the documentation says: “Separating allocation from initialization gives you individual control over each step so that each can be modified independently of the other.” I.e., both steps can be customized, so they must remain separate so that you can customize either or both.

So, there are two practical reasons why Cocoa’s designers separated allocation from initialization.

But let’s revisit this with modern eyes:

  • As I mentioned, in modern Cocoa, initializing an instance again is risky at best. In practice, I don’t think anybody does it, and if anybody does, they probably feel guilty about it and mean to refactor that code “someday”.
  • Nobody uses zones anymore.

That blows those two reasons away.

So, let’s imagine what life would be like if they had never existed in the first place, and allocation and initialization had remained one task:

+ (id) newWithFramistan:(Framistan *)framistan {
    id obj = [super new];
    if (obj) {
        obj->framistan = framistan;
    }
    return obj;
}

Right away, you can see several advantages:

  • We can name our local variable “framistan”, not “newFramistan” or anything like that.
  • No more assignment in condition (if ((self = …))).
  • No more assignment to self (which should make Wil Shipley happy).
  • Eliminates the problem of [super init] returning a different object, whereupon you would have to release the receiver. Since the receiver is the class, there is nothing for the upstream-initialized object to be different from. If the superclass wants to return an existing object, it can just do that.
  • Related to the first point, we no longer have a name conflict between instance variables and local (especially argument) variables. In init methods, we resolve this conflict with style rules, such as the aforementioned newFramistan for locals or m_framistan for instance variables; in this newWithFramistan: method, the conflict doesn’t exist in the first place.
  • There is never an uninitialized object that the caller could leave lying around. We’ve all seen (or written) code like Foo *foo = [Foo alloc]; [foo init];; in this alternate universe, such faux pas are impossible.

There are trade-offs:

  • It’s one line longer. (Depending on your employers’ level of cluefulness, this may be a small advantage.)
  • Since you’re not in an instance, you have to prefix every instance-variable access with obj->. I can see how this could get tedious; on the other hand, this is what prevents ivar-vs.-local name conflicts.
  • If you use object controllers that automatically prepare their content, they’ll use alloc and init, bypassing this initializer. I’ve never used the automatic-content-preparation feature, so this doesn’t affect me.
  • It’ll be less than familiar to anybody who hasn’t read this post, and it’s certainly a change from currently-typical Cocoa code.
  • Doing this in a subclass of a class that has an unusual designated initializer, such as NSView with its initWithFrame:, could get tricky.

My opinion is mixed. On the one hand, real problems with the init way of doing things are rare for anyone who knows the ropes. On the other hand, it sure is more straightforward, isn’t it?

What do you think?

* Presumably the same one most of us recognize as John C. Randolph, although there’s no direct evidence of this on his SO profile.