Solipsism Gradient

Rainer Brockerhoff’s blog

Browsing Posts in Software

OK, here’s what I wrote a few days ago, regarding the Mac OS X transition to Intel:
Rainer Brockerhoff wrote:

…Most Cocoa developers that didn’t call Carbon frameworks to any great extent, or that didn’t have to deal with complex binary files, were able to recompile their apps into the Universal (“fat binary”) format in a few hours or days. In contrast, most developers of Carbon apps of any complexity faced months or years of conversion.

I invited comments on Apple’s carbon-dev mailing list, and some people objected to the paragraph quoted above. In particular, Apple engineer Eric Albert wrote:

I’d probably moved more Mac OS X code to Intel than anyone else before the announcement — some of the iApps and a bunch of other apps, plus a ton of work in the OS — and of the code I’d worked on, the Cocoa apps happened to take more work than the Carbon ones. That was really nothing more than coincidence because the Carbon apps I was working on dealt with structured data better than the Cocoa ones, but there’s nothing inherently more complex about the Intel transition for Carbon than there is for Cocoa. Mathematica, which is most assuredly a complex Carbon app, took four hours to get up and running on Intel, faster than any other app I’ve seen.

The primary reason for some Carbon apps taking a long time to move to Intel was that they weren’t using Mach-O or Xcode at the time the transition was announced and both were required for Intel support.

Carbon apps already using Mach-O and Xcode came over to Intel fairly easily.

Well, that’s quite definite; I was wrong there. I was wondering why, though, and here’s what I found: the RDF is to blame… icon_wink.gif

Here’s what Steve Jobs said at the WWDC 2005 keynote, where I was physically present, and quite near the front too:

So, let’s take a look at this again: Widgets, Scripts and Java just work. Cocoa apps, literally a few days and your Cocoa app’s going to be running with an Intel version. Carbon apps, it’s to be a few weeks, a few more tweaks, although there are exceptions to that although we maybe overstating it here, which we’ll see in a minute. And and in Metrowerks we don’t know, you’ve got to get to Xcode. So the key here is getting to Xcode.

And I distinctly remember the same point being made later in the reserved “state of the union” sessions: click a checkbox in Xcode, “boom” for Cocoa… not that easy with Carbon.

There it is then. I don’t have any Carbon apps myself, and didn’t have to migrate anything from Metrowerks CodeWarrior either, so I thought Carbon was to blame for stuff like the Adobe Photoshop delay. I’ll update my original post below; thanks to everybody who sent in comments.

There’s one new thing on Safari 3 (for the Mac) that I found quite by accident.

Right-click on anything in a browser page and at the end of the normal contextual menu you’ll see a “Inspect Element” item. Selecting that opens a semitransparent “Web Inspector” HUD which shows tons of information about the document’s DOM structure, including CSS styles, element metrics, properties, and so forth.

The whole light-text-on-transparent-black look of these HUDs seems to be a matter of taste – I like them well enough in iPhoto, but on a white background, not so much – and there are some bugs; the top outline view doesn’t respond to the scroll wheel, for instance. Still, this seems to be a very useful tool for debugging your web pages; it’s making me want to (finally) redesign my site, even!

Ah, and this seems to work only if you have Safari’s debugging menu enabled. To enable it, quit Safari, open the Terminal and type:

defaults write com.apple.Safari IncludeDebugMenu 1

and it should work when you run Safari again.

People tell me this was already enabled in recent nightly WebKit builds, but I haven’t checked those for some time…

Update: as detailed here, you should do:

defaults write com.apple.Safari WebKitDeveloperExtras -bool true

if you don’t want the debug menu, just the inspector… and this is from January 2006! So this was there all along? Works in Safari 2, even? Heh.

Update#2: I just checked this… it doesn’t work in Safari 2 as such; you need a more recent build of WebKit.

XRay update

No comments

It’s been some time since I posted updates on XRay. Quite recently MacUser UK published a mini round-up on Finder utilities where, somewhat to my surprise, XRay scored 5 out of 5 against 4 competitors – and also was “Editor’s Choice”. (If anyone has that specific issue – 4/2007 I’d be grateful for a scan of the printed page.) Not bad for an utility which hasn’t been updated for quite some time!

This prompted me to review my sales graph which I had somewhat neglected lately. Here’s the current curve, with annotations:

The initial spike for the 1.0 release is no doubt due to several months of public beta. I wouldn’t necessarily say this would be applicable for all cases; XRay is targeted towards developers and more proficient users. During the public beta period I released new versions every month or so and took great care in replying to any comments and suggestions. So there was a pent-up demand and a ready-made userbase waiting to register their copy in the very first week.

After that, of course, sales decayed exponentially with a slight recovery when the reasonably significant 1.0.5 release came out, with subsequent releases nearly or completely vanishing in the noise – I suppose most people who needed it had already registered. Some other blips are due to the software being included in CDROMs. Still, for the last 3 years sales have stayed reasonably flat with a slight upwards trend detectable since the Intel Macs came out; no doubt this just reflects the expanding market. There are a few peaks (marked with “??”) which I have no ready explanation for…

Still, XRay 1.1 (the current release) isn’t an universal app, though it still runs fine under Rosetta. The downside is that the XRay Contextual Menu doesn’t work, as it’s called by the Finder, which (on Intel Macs) works only with universal plug-ins. However, it’s still possible (and even faster) to select an item in the Finder and XRay it by pressing shift-command-X.

Of course, as I’ve said here now and then, XRay II (2.0) is in the works. Unfortunately the universe has lately conspired to keep me from making any significant progress; still, I’m seriously determined to have a public beta out before the year is over. Hopefully sooner. Maybe much sooner. Stay tuned.

Brent Simmons has a long and thoughtful post about his way of doing large Cocoa projects. By all means read the original post and the comments. (Good reactions from Michael Tsai, Daniel Jalkut, Wolf Rentzsch, Blake Seely, I must have missed several others.)

Brent highlights some points: don’t overuse notifications, don’t overuse Key-Value Observing, bindings may be overkill for tables and outlines, C functions for global interfaces, flat source folder organization, learn tricks for fast project navigation. I agree with most. My own largest project is nowhere near’s Brent size of 345 .m files – perhaps also because I don’t mind larger files – but it’s not much simpler than NetNewsWire either. Anyway, bear in mind that my comments below just detail what works for me. YYMV and so forth.

Notifications. Everybody seems to agree they’re not a panacea. I listen to some Cocoa notifications and practically never generate my own. Notifications are great for posting notice of some application-wide event in the hope that some other parts of the application will want to know about it. That’s usually the case when some parts don’t know about other parts, or when one of the parts is a generic framework.

Like Brent, I prefer to use delegates for fast and specific notifications. Say a custom view is resized and someone needs to know when that happens; the logical pattern is to implement a delegate for that view and call it directly. Simple, fast, and easy to trace through. “Easy to trace through” is in fact my main debugging mantra. The bad thing about notifications is they’re difficult to step through in the debugger; you need to place a breakpoint at every listener. The obvious advantage over delegates is that you can have more than one listener – not that I ever needed more than one.

KVO and bindings: I haven’t had occasion yet to use those, although I’ll probably do so for preferences in XRay II. I tried using them in my first plug-in there but backed off fast; they’re certainly not suited to handling nested views that may be loaded and unloaded; the retain cycles get unmanageable. They’re also impossible to properly visualize in the current Interface Builder (though it seems that will change in Leopard?) and even harder than notifications to step through in the debugger. So I’d rather wait for a suitable application to present itself.

I suppose I also should point out that the upcoming Objective-C 2.0 properties look, so far, like another brilliant idea well-suited to specific purposes but not useable elsewhere. The property declaration syntax looks terrible, and the dot notation looks like Java. I can’t see myself using this any time soon – also, notice that the compiler will generate accessor code for them, meaning, you can’t step through.

High-level interface: in my first programs I noticed that I was jamming lots of methods into the application delegate. The app delegate is a singleton, so my other classes were full of lines like [[MyAppDelegate sharedInstance] checkSomethingWith:someStuff]. Later on I changed those to class methods like [MyAppDelegate checkSomethingWith:someStuff], and nowadays they’re just global C functions. I agree they may make it more difficult to refactor the design under certain circumstances, but after a while you learn to look ahead when deciding which functions to use. The only singleton object I have these days is the application delegate.

By the way, I use C functions a lot. Anywhere I see an instance method which doesn’t use “self” or any instance variable, it’s better to convert it into a C function. Same for most class methods. A bonus of C functions is that they’re harder to hack, of course.

Project Navigation: like Brent, I use the function popup a lot. I rarely have so many methods that sorting them into groups with #pragma mark is necessary. I use command-doubleclick and option-doubleclick a lot, and I keep AppKiDo open all the time. I noticed only recently that Xcode has a scripts menu with useful scripts and shortcuts, but the only one I use much is command-/ to comment and uncomment.

By the way, many people rave about using TextMate instead of Xcode for code editing. Apparently nearly all of those people are emacs fans who hate grabbing the mouse and prefer to do everything with memorized key shortcuts. Of course I’m an old fossil who still remembers the WordStar shortcuts and my shortcut neurons seem to be unable to learn new ones; I use the keyboard for cut, copy, paste and save, type short changes with my left hand, and for everything else I resent anything that forces me to take my right hand off the mouse. After all, that’s why we use Macs, right? </slight exaggeration for effect>

But then I suppose most of those people also like compiling their projects in the Terminal… Brent says, “Every time you touch the mouse, God kills a kitten”, but I’d say that for the command key instead icon_smile.gif

Flat folders: Yes, I too have a huge flat folder organization and 1 or 2 levels of grouping in the Xcode project. I never look at most of those files outside of Xcode anyway. I also include my readme and documentation files into the project, and edit them there (I create them in TextEdit however). Some people say this makes reusing code and source repositories harder. I prefer duplicating files or swatches of code when reusing; with some exceptions like RBSplitView, which I include as a subproject.

I seem to be notorious for not using version control systems; currently I keep my source on both my desktop and my laptop, and backup the entire project folder to a new disk image now and then. I very rarely need to refer to older versions anyway – I tend to comment out code instead of deleting it. I may try out Xcode 3’s subversion support, hopefully it won’t make me use the Terminal for anything. Of course, I’ve never worked in a programming team or had to share code with somebody else; blame it on history.

Rosyna asked on the carbon-dev list:

But it makes me wonder, is there anyway on Mac OS X to generate a”fast path” from an FSRef? That is, a path that is just the supershort volfs version of the path?

I need to use this myself now and then, so here’s a code snippet that does that:

#import <Carbon/Carbon.h>
#include <sys/mount.h>
const char* shortPath(FSRef* ref) {
   FSCatalogInfo info;
   if (FSGetCatalogInfo(ref,kFSCatInfoVolume|kFSCatInfoNodeID,&info,NULL,NULL,NULL)==noErr) {
      FSRef root;
      if (FSGetVolumeInfo(info.volume,0,NULL,0,NULL,NULL,&root)==noErr) {
         char* path = calloc(1,PATH_MAX+1);
         if (FSRefMakePath(&root,(UInt8*)path,PATH_MAX)==noErr) {
            struct statfs fs;
            if (!statfs(path,&fs)&&(fs.f_flags&MNT_DOVOLFS)) {
               snprintf(path,PATH_MAX,"/.vol/%lu/%lu",fs.f_fsid.val[0],info.nodeID);
               return path;
            }
         }
         if (FSRefMakePath(ref,(UInt8*)path,PATH_MAX)==noErr) {
            return path;
         }
         free(path);
      }
   }
   return NULL;
}

To use it, pass in your FSRef and you’ll get one of these back:

  • A short volfs path, if the volume supports volfs, or
  • A normal path if the volume doesn’t support volfs and the path is shorter than PATH_MAX, or
  • NULL.

If the return value is not NULL you’re responsible for freeing the path buffer after you’re done with it.

There are some issues with volfs paths you need to be aware of. The canonical reference here is Technical Q&A QA1113: The “/.vol” directory and “volfs”, which says:

WARNING:

Under no circumstances should your application construct paths within “/.vol”. This area of the file system is reserved strictly for the Carbon File Manager. The structure of the “volfs” file system is likely to change in a future releases of Mac OS X. You must use the following description of the “volfs” path structure for debugging and performance analysis only.

If you pass the path generated by my code snippet to any BSD routine it should work. You should however treat the path as opaque and not rely on its contents. About the only thing that also works is, if your FSRef points at a directory, you can concatenate the UTF8 name of a contained file (preceded by a slash) onto that path – you can’t add more than one though.

The snippet relies on one non-documented feature of the statfs call, namely, that the volfs volumeID is returned in the f_fsid.val[0] field. Needless to say this can break anytime in the future, and you may not want to rely on this for shipping applications. That said, it would certainly be useful to have the File Manager return a guaranteed short opaque path that could be passed to BSD calls. I plan to file a bug requesting this.

As QA1113 says, this could break in any future version of Mac OS X – I’m sure it works from 10.1.5 up to 10.4.9 though. You might want to insert a stat() call before returning the volfs path, if you’re really concerned about that… this is left as an exercise for the student.

Regarding the new Leopard shipping date, Rosyna says October is still spring – spring in the southern hemisphere, that is. As I’ve said before, Apple should think more globally and if that’s the first evidence for it, I approve… icon_smile.gif

Update: best summary of the situation from Wil Shipley.

Leopard is delayed for 4 months – until October. John Gruber has a good analysis, as does Daniel Jalkut.

A couple of weeks ago I wrote:
Rainer Brockerhoff wrote:

Even so, people who have not seen anything of Leopard beyond some leaked screenshots wrote excitedly about a MacWorld release, then about a March release, then when their wild predictions aren’t confirmed start to moan that “Apple’s been having trouble getting Leopard out” and now, even, that “Leopard had reportedly been delayed until October”. I really hope that Apple will show more details before WWDC, but I won’t be too surprised if they don’t.

The reference was to this DigiTimes story, which I didn’t even want to link to at the time because it sounded so absurd. Well, looks like they got it right, although the excuse for the delay is the iPhone, not Boot Camp. Although this is not stopping some people arguing that one of things apple will do during the extra months is converting Boot Camp into a Parallels-style virtualizer – something I’d previously described as likely to be implemented in firmware, until they took the TPM out of newer Intel Macs.

In retrospect, it’s not too surprising. Unusually, Apple is releasing 3 major products this year – TV, iPhone and Leopard – and all run some form of OS X despite having very different target markets and form factors. (Also unusually for Apple, all 3 were pre-announced.) So far, only the iPhone hasn’t been delayed, and clearly Apple felt that delaying all 3 would be a serious PR loss. Ergo, putting people to work on the iPhone makes some sense, supposing Apple managed to avoid the mythical man-month effect.

It’s still difficult to assess what this means for the upcoming WWDC. Sure, a feature-complete build will be available there, but unless something revolutionary new thing is revealed, it may not have much impact. Launching the iPhone there won’t be a big thing for developers unless a SDK is announced. I won’t be able to go this, so it seems I won’t miss much…

Folks on the #macsb IRC channel were talking about testing if an application was being run from a disk image, and it occurred to me that some code from XRay (already being adapted into XRay II) would be suitable for that. They suggested making a category on NSWorkspace, so here it is.

So the sample app project has a category on NSWorkspace which takes a path argument and returns a NSDictionary with some details about the volume and device. The app shows the attributes for its own path first, then you can check any others. Easy to test if the path points into a disk image or network drive, too. Please read the “ReadMe” file for details and caveats.

Suggestions are welcome. Please test this on your system and on any weird disk images, external drives or network volumes, and send me the results if they don’t look OK.

Photos licensed by Creative Commons license. Unless otherwise noted, content © 2002-2024 by Rainer Brockerhoff. Iravan child theme by Rainer Brockerhoff, based on Arjuna-X, a WordPress Theme by SRS Solutions. jQuery UI based on Aristo.