Quick Explanation of the Term "Application Bundle"

Follow-up to my previous post about receipt files. Again, this is Mac-centric.

WHAT IS AN APPLICATION BUNDLE?

"Application bundle" is Cocoa developer terminology for an application as it exists in the file system of your computer. The application consists of a number of files organized in a directory. The directory has special attributes and has a specific subdirectory structure.

WHERE IS THIS DIRECTORY? ALL I SEE IS THE APPLICATION FILE.

You only think you see a regular file. When you see an application icon in the Finder, such as the Safari icon, it looks like any other file icon. However, the Finder is telling at least two and possibly three lies about the application.

LIE #1: HIDING THE .app EXTENSION

On the file system, the name of the application is not actually "Safari" (for example) but "Safari.app", with a ".app" extension.

You can see all the .app extensions in Terminal:

ls /Applications

You can also see an application's filename in the Finder by selecting the application icon and doing a Get Info. You'll see the ".app" extension. Alternatively, if you go to Preferences > Advanced and turn on "Show all filename extensions", you'll see the .app extensions for all apps.

LIE #2: MAKING A DIRECTORY LOOK LIKE A FILE

An application is not a regular file, as it appears to be in the Finder, but a directory with special attributes and specific subdirectory structure. Such a directory is called a "bundle".

You can see the subdirectory structure in Terminal:

ls -l /Applications/Safari.app
ls -l /Applications/Safari.app/Contents

You can also see the directory structure in the Finder by right-clicking the application icon and selecting "Show Package Contents". You will see there is a subdirectory called "Contents", and within that there is a bunch of other stuff.

LIE #3: POSSIBLY A DIFFERENT NAME ALTOGETHER

Usually the Finder displays the name of the application as the directory name minus the ".app" extension. Thus, "Safari" instead of "Safari.app", "Contacts" instead of "Contacts.app", etc.

However, it is possible for applications to specify a different name to display in the Finder. The main reason for this is to localize the displayed application name. It is very rare to encounter this "lie" if English is your Mac's primary language.

Search for the term "CFBundleDisplayName" for the nuts and bolts of how developers get their apps to do this.

Quick Explanation of the Receipt File

I was explaining the MAS receipt file to a friend and decided to write a blog post instead of an email, on the principle Scott Hanselman has brilliantly advocated that we should conserve and amplify the limited number of keystrokes we have left in us.

I'm purely a Mac developer at the moment, but as far as I know this high-level explanation applies to iOS as well. No idea about watchOS.

WHAT IS THE RECEIPT?

The receipt is a file on your computer used for DRM of purchases from the App Store. There is a separate receipt for each app.

The receipt file contains:

  • Identifying information about the computer on which the app is installed — specifically, the MAC address of the device's primary network interface. Note that "MAC address", with the "MAC" in all caps, is a networking term. Nothing to do with "Mac" as in "Macintosh".

  • Identifying information about the app that the receipt is for — specifically, the app's bundle ID and version number.

  • Purchase history. Information about the app purchase and any subsequent in-app purchases.

WHERE DOES THE RECEIPT LIVE?

The receipt file is located inside the application bundle. On the Mac, it is at Contents/_MASReceipt/receipt. (If you don't know what the application bundle is, I've written another quickie blog post explaining it.)

WHO IS RESPONSIBLE FOR DRM?

The system is responsible for creating the receipt. By "system" I mean the OS in conjunction with the App Store. The system code-signs the receipt to prevent tampering. It's the job of Apple's developers to have gotten this right.

The application is responsible for validating the receipt. It's the job of the app developers to get this right.

WHEN DOES THE RECEIPT GET WRITTEN?

The receipt gets created on your computer when you download the app from the App Store. The receipt is then updated in the following situations:

  • If a newer version of the app becomes available on the App Store, the receipt is updated when you upgrade to the newer version.

  • If the app supports in-app purchases, the receipt is updated whenever you do an in-app purchase.

  • When you "Restore Purchases", the receipt is updated.

Here's what I mean by "Restore Purchases". Certain types of in-app purchases apply to all computers on which you have installed the app, not just the computer on which you made the purchase. A typical example would be an IAP that unlocks premium features. If you made such a purchase on a different computer, you may need to explicitly "restore" that purchase on the computer you are using. Apple's App Store rules require the app to provide a way for you to do this. Usually the app provides a button or menu item with a name like "Restore Purchases".

HOW DOES THE APPLICATION USE THE RECEIPT?

The application does two things with the receipt:

  • It validates the file contents to confirm the receipt hasn't been tampered with.

  • It checks in-app purchases to see what enhanced functionality the user has purchased. In-app purchases may include permanent "unlocking" of features, or they may be subscription-based, in which case the app should check the expiration dates of the subscriptions.

Both of these steps are performed by parsing the receipt file, which is a science in itself. There's an excellent article on objc.io that explains what is required:

You may wonder why Apple hasn’t provided a simple API to validate the receipt. For the sake of demonstration, imagine that such a method exists (for example, [[NSBundle mainBundle] validateReceipt]). An attacker would simply look for this selector inside the binary and patch the code to skip the call. Since every developer would use the same validation method, hacking would be too easy.

Instead, Apple made the choice to use standard cryptography and encoding techniques, and to provide some help — in the form of documentation and WWDC sessions — for implementing your own receipt validation code. However, this is not an easy process, and it requires a good understanding of cryptography and of a variety of secure coding techniques.

Of course, there are several off-the-shelf implementations available (for example, on GitHub), but they are often just reference implementations and suffer from the same problem outlined above if everybody uses them: it becomes very easy for attackers to crack the validation code. So it’s important to develop a solution that is unique and secure enough to resist common attacks.

MORE LINKS

Swift's Range Operators

I was going to wait until I had more first-hand experience with Swift before blogging any opinions, but then I remembered this is the Internet. So here I am, late to the party, weighing in on Swift's range operators, about which I have a definite opinion.

Swift's original range operators, as defined in the first beta of Xcode 6, were:

  • x..y for a half-closed range (including x, excluding y)
  • x...y for a closed range (including both x and y)

There were lots of complaints about this choice, mostly in two categories as I recall:

  • Complaint #1: .. and ... are too easy to confuse with each other, the same way = and == are easy to confuse in C.

  • Complaint #2: .. and ... are too easy to confuse with the same operators in Ruby, which are defined with the opposite meanings.

Note that these complaints aren't about personal taste. They're about making it too easy to write buggy code.

Here is a complaint that absolutely nobody made, so please don't take it too seriously, but it did occur to me as a possible annoyance:

  • Complaint #3: Some people want ... to be a system macro that automatically gets replaced with an ellipsis character.

A few people, including me, have proposed this alternative, which I am still convinced is best:

  • x..<y for half-closed
  • x..=y for closed

Here's what I like about this option:

  • There is a parallel structure to the operators. ".." means this is a range, followed by a qualifier, either "<" or "=", that indicates whether the last element of the range is less than or equal to y.

  • Neither operator is a substring of the other. You can't make the mistake of typing one too few characters.

  • The meanings of the operators are clear from their appearance (addressing Complaint #1). You won't have to pause each time to ask yourself "Which one was the closed one again?"

  • The operators don't conflict with other languages (addressing Complaint #2). When I posted my suggestion, I didn't think either operator had a precedent in any other language. It turns out ..< is used in Groovy, but it has the same meaning there as here.

In Xcode 6 beta 3, one of the range operators was changed. As of this writing, the operators are:

  • x..<y for half-closed
  • x...y for closed

This is fine with me, although I may change my mind if I ever start programming in Ruby. By only changing one of the two operators, the Swift designers[1] leave them half-open, if you will, to Complaint #2.

I want to mention one more proposed alternative that seems nice in theory but that I don't think should be adopted:

  • [x..y) for half-closed
  • [x..y] for closed

This notation is already familiar to people with a little math, and easily learnable by anyone else. It's concise. It's unambiguous. It allows for the possibility of variations like (x..y] and (x..y).

But I think it could be open to Complaint #1. Depending on the font the programmer is using, and the resolution of their monitor, and how sleep-deprived they are, a parenthesis could maybe be mistaken for a square bracket. Or the difference might not be striking enough to register when they're eyeballing the code, looking for why the program crashed.

Furthermore, I think mismatched brackets and parentheses could cause headaches in text editors other than Xcode. When we see an expression like that, we're used to being able to double-click one of the delimiters to select the whole expression. I don't know, maybe existing text editors could easily be updated to handle that, but it seems like a potential problem to me, and I do think this kind of consideration should influence language design. It's worth looking for an option that both makes theoretical sense and plays well with the tools we use in practice.


[1] To the extent there is any such person other than Chris Lattner.

Faking "switch" with an object value

Jeff Kelley started a thread on the objc-language mailing list with this idea:

I would love to see a switch statement we could use for objects, testing equality with each case: statement. @switch would work nicely as the name, and I envision it working like this:
@switch(myString) {
    case @"hello world":
        // Do something
        break;
    case @"another one":
        break;
}
This would be equivalent to writing the code using if statements and sending -isEqual: messages, but with a much more readable control flow.

The blocks approach

One suggested approach was to use a dictionary to map each "case" value to a block that should be executed when the "case" value matches the "switch" value. Jeff Biggus posted this solution mainly as an academic exercise, but I think it's about as tidy as the blocks-based approach gets:

typedef void (^voidBlock)(void);
 
#define swoosh( test_var__, action_dictionary__... ) \
        ((voidBlock)action_dictionary__[test_var__])();
 
[...]
 
NSString *test = @"that";
swoosh( test, @{
        @"this" : ^{ NSLog( @"found this" ); },
        @"that" : ^{ NSLog( @"found that" ); },
});

Nicolas Bouilleaud posted an alternative solution using +resolveInstanceMethod: that allows you to write:

[[@"foo" switch]
 case:@"bar" :^{ success = NO; }
 case:@"baz" :^{ success = NO; }
 case:@"foo" :^{ success = YES; }
 ];

I'm not crazy about using blocks for a few reasons:

  • You have to think about whether you need to use __block variables.
  • You can't put break, continue, or return statements in the blocks and have them work as they would in an analogous switch statement; often their very presence would be a syntax error.
  • If you use a dictionary of blocks, the "case" objects have to conform to NSCopying so that they can be dictionary keys. Also, as Nicolas points out, if you use a dictionary, you can't specify the order in which the cases are tested. So, no dictionaries; but you can imagine a similar approach using an array.
  • Xcode's auto-indenting of blocks looks really, really horrible. In theory, the typographical quirks of an IDE have nothing to do with the soundness of a technical approach, but Xcode is so bad about this that I can't ignore it. For example, if I put the first NSLog above on its own line, Xcode does this:
swoosh( test, @{
       @"this" : ^{
    NSLog( @"found this" );
},
       @"that" : ^{ NSLog( @"found that" ); },
       });

objswitch, objcase, endswitch

I don't know how original this is, but by using a few macros and a small class used behind the scenes, I came up with a different approach that is essentially syntactic sugar around nested else-if statements. Here's an example of how it looks, as formatted by Xcode:

objswitch(someObject)
objcase(@"one")
{
    // Nesting works.
    objswitch(@"b")
    objcase(@"a") printf("one/a");
    objcase(@"b") printf("one/b");
    endswitch
 
    // Any code can go here, including break/continue/return.
    // Xcode will indent it nicely.
}
objcase(@"two") printf("It's TWO.");  // Can omit braces.
objcase(@"three",  // Can have multiple values in one case.
        @"tres",
        @"trois") { printf("It's a THREE."); }
defaultcase printf("None of the above.");  // Default case is optional.
endswitch

I would argue this is even a tiny bit nicer than switch/case syntax, because you don't need unsightly break statements to keep the cases from bleeding into each other.

If someObject is @"one", the output is

oneb

If someObject is @"tres", the output is

It's a THREE.

In this example all the "case" values are strings, but they can be any object.

The "keywords" objswitch, objcase, objkind, and endswitch are actually macros. There is a simple class called ObjectMatcher that is instantiated by objswitch. You can see the code on GitHub.

objkind

Some people mentioned wanting similar syntax for testing the class of the object rather than its value. Testing an object's class is often a sign of suboptimal design (see here for a brief discussion, here for my thoughts on the matter), but for those occasions when you decide it's the right approach, you can use my objkind macro:

objswitch(someObject)
objkind(NSNumber) { printf("It's a NUMBER."); }
objkind(NSString) { printf("It's a STRING."); }
objkind([NSArray class],
        [NSDictionary class],
        [NSSet class]) printf("It's a collection.");
endswitch

Note that if you're only passing one class name to objkind, you can just give the class name:

objkind(NSNumber)

But if you pass multiple classes, you have to say [MyClass class] or [MyClass self] (or, if you prefer, MyClass.class or MyClass.self) for every item after the first one. This is a limitation of __VA_ARGS__ macros. I prefer all the items to look the same — hence:

objkind([NSArray class],
        [NSDictionary class],
        [NSSet class])

Like objcase, objkind is just a wrapper around a nested else-if statement, so you can freely mix objcase and objkind within the same objswitch.

selswitch, selcase

One place I might like a similar construct is for doing a switch statement on a selector. I have validateUserInterfaceItem: methods all over the place with lots of nested if-statements like this:

SEL itemAction = [anItem action];
 
if (itemAction == @selector(selectSuperclass:))
{
    // ...
}
else if (itemAction == @selector(selectAncestorClass:))
{
    // ...
}
else if ((itemAction == @selector(selectFormalProtocolsTopic:))
         || (itemAction == @selector(selectInformalProtocolsTopic:))
         || (itemAction == @selector(selectFunctionsTopic:)))
{
    // ...
}

I created selswitch and selcase macros that let you do this:

selswitch([anItem action])
selcase(@selector(selectSuperclass:))
{
    // ...
}
selcase(@selector(selectAncestorClass:))
{
    // ...
}
selcase(@selector(selectFormalProtocolsTopic:),
        @selector(selectInformalProtocolsTopic:),
        @selector(selectFunctionsTopic:))
{
    // ...
}
endswitch

I haven't decided whether the improvement is big enough that I'd use this rather than plain old nested ifs, especially since validateUserInterfaceItem: is called very frequently and should be as fast as possible.

[UPDATE: I've made several edits since I first published this post, ranging from fixing typos to inserting a sentence or two. I was originally flagging each change, but to reduce clutter I decided just to add this mention at the bottom.]

Writing a .service bundle

You can provide system services (items that appear in the Services menu) in two ways: through an application (YourApp.app) or through a standalone service (YourService.service). The first way is well documented, but I've found it hard to find instructions for the second way.

The first way: a regular .app

Your Cocoa application can provide services that appear in the Services menu. Apple's "Services Implementation Guide" explains how to do this. Basically:

  • Create a class (or use an existing class) with one method for each service. Each service receives input and optionally returns output by way of NSPasteboard.
  • Add an "NSServices" key to Info.plist with info about each service.
  • At some point during application startup, call NSRegisterServicesProvider().

Put the application in /Applications, or a subfolder thereof, to get the system to detect the new service(s).

When an application service is invoked, the application becomes active. There seems to be no way to avoid this. At best you can immediately hide the application, but there will still be a flicker as windows appear and disappear.

UPDATE: Mark Munz offered this tip on the cocoa-dev mailing list:

[T]he solution I used to prevent Services from bringing the app forward is to have a background (LSUIElement) helper app that acts as the NSServices provider. Depending on what you need to do, you could either support the service directly in the helper app or use it to talk to the parent app to perform the necessary work (without requiring it to activate). I use the second approach.

The second way: a .service bundle

If you want a service that is purely a background operation, you can create a standalone service that has no UI. It's very simple once you know how, but I haven't found a lot of help online, although some books discuss it and you can find examples on GitHub by searching for NSRegisterServicesProvider.

I expected a "System Service" template in Xcode, but there is none. Instead, you use a "Cocoa Application" project and code it just like a regular application with services except:

  • Change the target's wrapper extension from "app" to "service": Project > Target > Build Settings > Wrapper Extension.
  • Make it a background application by adding to Info.plist: LSUIElement = YES. (This is the "Application is background only" item in the popup menu that appears in Xcode's plist editor.)
  • Remove resources you won't need, like MainMenu.xib, AppDelegate, and Credits.rtf.
  • Edit main.m to instantiate the service-provider object and enter a run loop. Here's an example.

Build the project and copy YourService.service to ~/Library/Services. You may have to relaunch apps to get them to see the service.

Tips

  • Instead of editing Info.plist to add the NSServices entries, you might prefer to use Xcode's UI. I don't know when this was added to Xcode, but you can go to Project > Target > Info and there's a "Services" area at the bottom. It's easy to miss if you don't know it's there.

  • To uninstall the service, remove YourService.service from ~/Library/Services. You won't be able to delete it if the service has a running process, so you might have to kill the process first.

  • If the service doesn't appear in the Services menu, you may have to force the menu to be reconstructed. Unfortunately there's no command you can call from the command line. It's trival to write one though — all it has to do is call NSUpdateDynamicServices().

See also

As I mentioned, Apple's "Services Implementation Guide" has plenty of detail on writing application services, but as far as I can tell the only help it gives on standalone services is this one line:

> To build a standalone service, use the extension .service and store it in Library/Services.

The breakthrough that got me going was when I found example code on the Timac blog. I already had implemented a service in an application. By looking at Timac's code and doing monkey-see-monkey-do, I got my first standalone service working.

I then realized I could find plenty more examples by searching GitHub for "NSRegisterServicesProvider".

Here's the service I wrote. It copies method names to the clipboard so you can paste them in emails, code comments, docs, and so forth.