Redistributing Apple's sample code

In the example source code that Apple gives to developers, they put licensing terms at the beginning of every file. As I read them, the terms essentially say: "You may redistribute this file without modification, but only if you leave these licensing terms in the file."

Isn't that a tautology? If I share the file without modification, then the licensing terms are already in the file. If I remove the licensing terms from the file, then it's no longer "without modification", and I am then free to share the file sans licensing terms. That's what I would naively think. Does the law include a rule of some kind to avoid this circularity?

Here's the language as it appears in every source file (excerpted, emphasis added):

In consideration of your agreement to abide by the following terms, and subject to these terms, Apple grants you a personal, non-exclusive license, under Apple's copyrights in this original Apple software (the "Apple Software"), to use, reproduce, modify and redistribute the Apple Software, with or without modifications, in source and/or binary forms; provided that if you redistribute the Apple Software in its entirety and without modifications, you must retain this notice and the following text and disclaimers in all such redistributions of the Apple Software.

Here's the reason I ask. I've been looking at a particular Apple example, and I felt compelled to fiddle with it. I applied my coding style, edited the comments, renamed things (including the project itself), added a delegate protocol, and fiddled with the UI. I feel the result is better than the original; maybe not hugely, but enough that I want to make the modified code publicly available.

I did this once before with an ancient example project called "Moriarity". At that time I removed the duplicated licensing terms from all the source files and put them in an accompanying file called LICENSE.txt. (Come to think of it, the legalese above makes more sense when the licensing terms are in their own file.) Now I'm wondering if that was really necessary. If not, then I'd rather not include a pointless license file with the project. Or rather, I'd rather include my licensing terms, which are that you're free to use my changes however you want, with or without attribution. Of course, I'd mention that the code is derived from an Apple example.

There are a couple of other issues that make me hesitate. For one thing, this is one of the example projects from WWDC, which means you need a developer login to get the original version from Apple. I'm not too worried about this, because this example is Mac-only, and unlike the iOS 6 SDK, the 10.8 SDK is now public. [Update: This example project is now public, and actually had been for a few days already when I wrote this post. It's the "Scene Kit Document Viewer" project I mention here.]

The other issue is that the example project includes artwork — a 3D model in a .dae file — that clearly belongs to Apple. I'd like to use this model, but I suppose if I had to I could find a public domain one to replace it with.

I'm probably worrying way too much about this, especially given how tiny the code in question is. I'm going to go out on a limb and guess that Apple has bigger legal fish to fry regarding people copying stuff. I should probably go ahead and publish my version of the code, and just decide: either include Apple's licensing terms just in case, or leave them out on the forgiveness-rather-than-permission principle. What's Apple going to do, get me in trouble for writing the exact code they advise us to write?

Method-aware doc searches

I finally got around to updating AppKiDo so that the various URLs it uses point to appkido.com rather than the now-defunct MobileMe site. The new version requires 10.5; I got tired of not using fast enumeration.

While I was at it I added the system service I mentioned I was thinking about, and I used NSServiceCategory to put it in the "Searching" category of the Services menu. I considered putting it in the "Development" category, but I think what AppKiDo does is more akin to Dictionary than to Instruments.

Services appkido

I made the search service "method-aware", which means it tries to detect method names in your text selection. I'm hoping other doc-search apps will add this feature. They can use my simple method-parsing class, if it helps. For people who have use for the method extraction but don't want to launch AppKiDo, it might be nice to put it into a standalone Service, but I don't know if I'll get to that.

The rest of this post will be an explanation of the "method-aware" feature, copied from the release notes.


"Look Up in AppKiDo" is a service that you can invoke from any application where you have selected some text. It activates AppKiDo and performs a search for that text.

Often what we want to search for is a method name. AppKiDo tries to help by determining whether the selected text contains an Objective-C message-send or method declaration. If so, it searches for that method name. Otherwise, it searches for the literal text you have selected.

For example, in Xcode if you have [self flyToX:100 y:200 z:300], you can double-click one of the square brackets to select the whole expression, then invoke this service. AppKiDo will search for the method name flyToX:y:z:.

If you happen to be in BBEdit, where double-clicking a bracket selects the text inside the brackets, the service should still work. If there is leading whitespace or a cast, or newlines or comments anywhere, it should still work, so if you have lines like this you can select them all and then invoke the service:

(void)[self flyToX:100  // cast to void to discard the return value
                 y:200
                 z:900 /*300*/];

Note that "Look Up in AppKiDo" doesn't work if there is an assignment in the selected text. For example, it won't work if you select this whole line:

BOOL didFly = [self flyToX:100 y:200 z:300];

The workaround is to select just the message-send — the part after the "=".

Another intended use is when you're looking at code that declares a method and you want to search for that method name. For example, you can select these lines and it will search for browser:child:ofItem: (the "-(id)" will be ignored):

- (id)browser:(NSBrowser *)browser
        child:(NSInteger)index
       ofItem:(id)item

This service assumes well-formed Objective-C. You might get unexpected results otherwise. If there are nested messages, it uses the top-level one. The algorithm mainly looks at punctuation — delimiters like brackets and a few other characters that need special treatment. The basic idea is that it ignores anything between delimiters, like (blah blah blah), [blah blah blah], or {blah blah blah}. For this reason it should work if your selected code contains blocks or the new object literals.

If you use the "Look Up" service, remember to assign a hotkey in System Preferences > Keyboard > Keyboard Shortcuts > Services for maximum convenience.

What kind of service is this?

I asked what I thought would be a simple question on cocoa-dev:

I've added a system service to my app. I'd like it to appear in the "Search" group of the Services menu (where "Look Up in Dictionary" and "Search With Google" are) rather than the "Text" group.

I would have guessed there is some key-value pair I could set in the NSServices dictionary in Info.plist, but as far as I can tell my NSServices looks just like Safari's.

Here's what I meant by the "Search" group (actually I meant "Searching"):

Services searching

I waited a few days and no one replied, so I poked around some more. The short answer is that you add an entry to the NSRequiredContext dictionary using the undocumented key NSServiceCategory:

<key>NSRequiredContext</key>
<dict>
	<key>NSServiceCategory</key>
	<string>Searching</string>
</dict>

You can't create your own category. If you change "Searching" to "My Great Services", the Services menu doesn't add a "My Great Services" category containing your service. Instead, your service goes back into the catch-all "Text" category. There are at least eight names you can use:

  • Pictures
  • Internet
  • Files and Folders
  • Messaging
  • Searching
  • Text
  • Development
  • General

I got this list from System Preferences, in the Keyboard > Keyboard Shortcuts > Services pane:

Service category names

I had looked in the Info.plist files of Safari and Dictionary, but they don't use NSServiceCategory or I'd have found this answer a lot sooner. Nor does Mail, which appears in Services under "Messaging". Besides using Info.plist, Cocoa must have a secret registry somewhere that maps apps to Services categories.

I only discovered NSServiceCategory, which finally gave me something good to Google, when I thought to look inside Twitter and Tweetings, two apps that also manage not to be in the "Text" category. Instead of a category name, those apps use the UTI "public.item", which puts their services under "Files and Folders". That seems odd to me, but maybe that's their way of breaking out of the big undifferentiated "Text" category.

You can find other apps that use NSServiceCategory by running this command and grepping the results:

/System/Library/CoreServices/pbs -dump_pboard

Using NSServiceCategory was unofficially advised by Peter Ammon back in 2009. I've filed Radar #11945677 asking Apple to make it official in the Services Implementation Guide so that users can see their services properly categorized.


UPDATE: NSServiceCategory isn't the only setting that affects what category the service goes into. I noticed the Versions app doesn't have a NSServiceCategory setting, yet it appears in the "Internet" category, because of its NSTextContent setting:

<key>NSRequiredContext</key>
<dict>
	<key>NSTextContent</key>
	<string>URL</string>
</dict>

I updated my Radar to ask that this be documented as well.

Hotkeys for searching the Cocoa docs

Here's how to create global hotkeys for instantly searching the Cocoa docs using Dash, AppKiDo, or Xcode.

This whole exercise started when I saw this tweet by Matt Gemmell:

There’s a kind of zen calmness to the docs page for NSNull.

Since I have Dash installed, and since I've assigned a hotkey to its "Look up in Dash" system service, it took me all of two seconds, maybe less, to confirm this. I selected the word "NSNull", hit the hotkey, and there it was. Matt's right.

Here's where I assign the Dash hotkey, in System Preferences > Keyboard > Keyboard Shortcuts > Services:

Look up in dash

"Look up in AppKiDo"

UPDATE: You can ignore the rest of this post. I added a real system service to AppKiDo in version 0.991. You can configure a hotkey for the service just as you would for any other system service.

This got me thinking about adding a similar system service to AppKiDo. I wondered whether I should try to squeeze that into the upcoming release (which will have a few small changes, most importantly to point to appkido.com instead of MobileMe). But then I realized I could just use a keyboard macro utility (in my case, Keyboard Maestro) to accomplish the same thing. I created a keyboard shortcut that does the following: * Type Command-E, which is Mac standard for "Use Selection for Find". This puts whatever text is selected in your current app into the Find pasteboard. * Activate AppKiDo, which now displays the selected string in the Search field. * Type Shift-Command-F (which selects the Search field) and Return (which initiates a search). Look up in appkido Now I can look up NSNull in AppKiDo the same way as I did in Dash, by selecting text and hitting a key. This assumes AppKiDo has a browser window open and frontmost, but for me that's always the case. To search AppKiDo-for-iPhone, you'd need a separate hotkey. If you want to get technical, AppKiDo doesn't show the whole docs page, only one part of it at a time. To see the whole HTML page, and thus appreciate its zen-ness, you'd have to right-click and select "Open Page in Browser". And then you'd have to dismiss a dialog in Safari because that file is quarantined. So now we're talking maybe five seconds. Dash wins handily at displaying the whole page. ## The YoruFukurou problem While testing my "Look up in AppKiDo" shortcut, I discovered that YoruFukurou doesn't support the "Use Selection for Find" operation. It bugged me to have this edge case, so I created a variant of the shortcut just for YoruFukurou:
  • Type Command-C (copy to the clipboard).
  • Run the following AppleScript to activate AppKiDo and do the search.
    tell application "AppKiDo"
        activate
        search (the clipboard)
    end
Just for yorufukurou This uses the fact that AppKiDo can be scripted to do a search. I also use Keyboard Maestro's ability to have a keyboard shortcut do different things depending on which application is active, so I don't have to remember a separate shortcut for the YoruFukurou case. The reason I don't use this approach in all cases is that Command-C blows away the contents of the copy-paste pasteboard, whereas Command-E uses a different pasteboard. ## "Look up in Xcode" Finally, just for grins, I thought I'd do a similar shortcut for doing the search in Xcode. Xcode is very slow at searching the documentation, but it's useful for doing full-text searches of the complete documentation, as opposed to searching only the API reference docs based on the name of the API symbol. This shortcut uses the fact that in Xcode, hitting Shift-Option-Command-/ (aka Option-Command-?) always causes the doc window to be open with the Search field selected. * Type Command-C to copy the desired search string into the clipboard. * Activate Xcode. * Type Shift-Option-Command-/ to bring up the doc window, and Command-V to paste the search string into the search field. Look up in xcode Note that *within* Xcode there's already a shortcut for searching the docs for the selected text: Control-Option-Command-/ (last item in the Help menu).

[UPDATE: I'm getting better about editing my posts after publishing them, but I couldn't resist making a few changes. Nothing major.]

How many Apple IDs do I have?

Today I was setting up a fresh OS install and noticed that in the Mac App Store, my "Purchases" list was missing many items. Only a handful of apps were listed, when it should have been dozens.

Others have had this problem, and for some people this advice has worked:

  1. Select Store > View My Account and sign in.
  2. Look for a section headed iTunes in the Cloud, with a Hidden Purchases entry, and click View Hidden Purchases.
  3. Click Unhide for those purchases you wish to appear in your App Store Purchases window, then click Done.

When I tried this, I didn't see anything about iTunes in the Cloud or Hidden Purchases.

Then I remembered that I've had problems before with my Developer account where I got different behaviors depending on whether I logged in with "aglee" or "aglee@mac.com" as my Apple ID. I logged out of the Mac App Store as "aglee@mac.com" and logged back in as "aglee", and all my purchases appeared again.

I'm guessing that at some point I accidentally created two separate Apple IDs, not realizing that logging in as "aglee" at mac.com was not the same as logging as "aglee@mac.com". One of these days I'll see if I can get the accounts reconciled. It's annoying having this dual identity with an identifier whose very purpose is to tie together all the ways in which I use Apple services. Bad enough that Apple gave me an unwanted me.com email address.

[UPDATE: While logged into the "wrong" account, before realizing that was the case, I clicked on an app that I already owned, expecting it would be treated as a re-download, but of course it was treated as a purchase. I contacted Apple and got a refund right away, no hassle, for the redundant purchase. I used the customer support link at the bottom of the receipt email. I asked about reconciling the two accounts and was told: "I am sorry but it's not possible to merge two or more iTunes Store accounts together."]