I released version 2.1 of Album Artwork Assistant, my Mac OS X application for finding iTunes album cover artwork on the web.
This version lets you surf the web and pick images directly off web pages in an embedded web browser. This is useful if the image search doesn’t turn up suitable results and you have to hunt down the artwork. Watch this screencast to see how it works:
There are also some bug fixes and stability improvements, as listed in the release notes.
For Developers
Here are some observations for Cocoa developers.
WebKit
First off, WebKit is a fantastic library, I have used it in many projects and it’s always a joy to use it.
In this case I was impressed how easy it is to get information about and interact with the DOM elements loaded in a web view when the mouse cursor hovers over them. You get a delegate callback with a dictionary of useful information about the element. The dictionary content depends a bit on the type of the element. In the case of IMG elements, you even get the full URL of the image source, which is exactly what I needed in my application.
This delegate method allows the application code to do very interesting interactive things with the web content rendered in the web view; think about all the cool stuff an application can do if it has full access to the structure of the web content and doesn’t just have to deal with it as a dumb bitmap.
Another thing that’s very easy is to adapt the contextual menu contents when the user opens the menu over some DOM element.
Both features are provided by the WebUIDelegate protocol.
ImageKit
ImageKit flat out doesn’t work under garbage collection. See my bug report for the details. In short, old image objects stick around forever and don’t free the resources they use. More and more memory is consumed, but even worse, if you use the IKImageBrowserNSURLRepresentationType image type and supply http URLs, the dead objects will keep the HTTP socket open, quickly exhausting the available file descriptors.
In my application I could work around the open sockets problem by loading the images myself and then passing raw image data instead of the image URL to ImageKit. But the memory consumption is still a problem, the memory usage of the application grows steadily with every image search. I hope this gets fixed by Apple.
NSError
Related the the previous issue, NSError’s localizedDescription method crashes if the file descriptor table is full. This is bad because you start getting NSErrors from many APIs precisely when the file descriptor table is full. I filed a bug about this too.
Garbage Collection Debugging in GDB
The GDB commands info gc-references and info gc-roots are very useful to debug garbage collection-related problems (and it’s also interesting and educational to poke around with them).
Here I hit a breakpoint and inspected the images array:
(gdb) po images <NSCFArray 0x107eb30>( <TestImageBrowserItem: 0x107df10>, <TestImageBrowserItem: 0x102dbf0>, ...
Let’s check out its first item:
(gdb) info gc-references 0x107df10 0 Kind: stack rc: 0 Address: 0xbfffee9c Frame level: 0 Symbol: foo warning: can't find class named `IKImageBrowserCell' given by ObjC class object 1 Kind: object rc: 0 Address: 0x0106def0 Offset: 0x00000008 Class: IKImageBrowserCell 2 Kind: object rc: 0 Address: 0x0107b2a0 Offset: 0x00000020 warning: can't find class named `IKImageCellDatasourceProxy' given by ObjC class object 3 Kind: object rc: 0 Address: 0x0108ca60 Offset: 0x00000004 Class: IKImageCellDatasourceProxy
This shows that four locations in memory reference my image object. One is in a local variable foo on the stack (the high address, with Kind: stack), the remaining references are in other objects on the heap (the low addresses, with Kind: object).
In some situations it didn’t work for me, both commands would just hang forever without producing any output. One of them did produce output when I added a type cast in front of the object’s memory address:
(gdb) info gc-references (TestImageBrowserItem *)0x107df10
|


