Category Archives: Apple

Brent’s Swift Tension

Brent Simmons has been writing new code exclusively in Swift for a while now, and he recognizes omissions from the language that he still anticipates will be hard to overcome as Apple presumably moves toward incorporating Swift into its developer-facing frameworks. The Tension of Swift:

The Objective-C runtime allows AppKit and UIKit to provide some powerful features that I’d hate to do without: the Responder Chain, xib and storyboard loading, KVC, and the undo manager.

A key point he gets at is that however great Swift is, it’s only possible to use it to develop functional iOS and Mac apps because of the Objective C runtime still operating behind the scenes. Both AppKit and UIKit not only lean on the functionality of the runtime, but are designed with the runtime in mind.

Some major design priorities of the Swift language, namely type safety and compile time dependency binding, are at odds with the design priorities of 20 years of evolution in Apple’s frameworks. How and if that disparity will be reckoned by Apple remains to be seen.

I’m optimistic, because the Swift team has already made many concessions to make the language more compatible with the Objective C runtime. It strikes me as possibly non-optimal that a language that strikes the right compromise between Swift’s priorities and Objective C’s would start at the opposite extreme and work its way backwards, but that is what Apple seems to be doing.

Let’s hope they continue in that direction, and surprise us all with how well it all works out in the end.

Mac App Store Sandbox Testing

For months, many of us Mac developers have noticed that apps built for Mac App Store submission could no longer be tested using iTunes Connect “sandbox” users. Previously, a sandbox user account could be used to authenticate and download a _MASReceipt for a Mac app, to ensure that in-app receipt validation is working as expected. After updating to 10.11.2, many of us noticed that this functionality suddenly stopped working:

At first, we assumed it was a bug. But as time went on, it started to seem as though it could be related to Apple’s announcement that one of its key certificates was expiring.

Still, the communication from Apple about this issue was poor enough that it wasn’t obvious what exactly we needed to do. Even though the page linked above has a section explicitly listing what Mac developers are expected to do:

You can verify your receipt validation code is compatible with the renewed certificate in the test and production environments. A pre-release version of the Mac App Store Update for OS X Snow Leopard beta is now available.

The linked “pre-release version” was no-doubt once a valid link, but at least through my account, it now leads to a permission-denied type failure page.

So what do we do? Fortunately, after chatting through the problem with some friends, Chris Liscio deduced the key, somewhat-obvious in retrospect steps to test your Mac app for compliance with the new certificate, while getting sandbox testing working again at the same time:

  1. Install the new certificate from Apple. In my case, I opened it in Keychain access and added it to the System keychain, where the older, expiring certificate currently resides.
  2. Reboot.

The second step is the important one. If you just install the certificate and expect everything to work, you’ll be sadly rebuffed with continued failures. Reboot. Let the system soak in the new certificate, then try re-launching your Mac app built for submission to the Mac App Store. It will prompt you, as you had previously expected it to, for your sandbox credentials. When you enter them, instead of insisting you set up a new iTunes customer profile, it will just launch. Or, if it doesn’t, maybe you’ve got some problems to work though in your receipt validation code.

Presenting HTML On Apple TV

In a recent post on my Bitsplitting blog, I complained that Apple’s forbiddance of web views on Apple TV would limit many developers who use HTML tastefully in the construction of their interfaces. I suggested that Apple might allow developers to use web views, but limit their usefulness as full-fledged web browsers.

Since writing that article, I discovered a potentially useful “backdoor” of sorts that could allow developers to continue using HTML to some extent for visual formatting of content in their user interfaces.

UITextView supports attributed strings, and NSAttributedString supports being initialized with HTML. Historically on the Mac at least, this capability was famously poor, but I seem to recall reading that it had been boosted at some point by using WebKit behind the scenes to do a more proper conversion.

Here’s an example of how an Apple TV app can convert literal HTML content into a visual form. This is, so far as I can tell, compliant with both the letter and the spirit of Apple’s guidelines for using the SDK:

NSString* staticHTMLContent = @"<div style='font-size:6em;'><strong>Hello</strong> <span style='font-family:courier;'>there</span>, I'm <span style='color:red;'>HTML</span>!</div>";

NSAttributedString* myHTMLString = [[NSAttributedString alloc] initWithData:[staticHTMLContent dataUsingEncoding:NSUTF8StringEncoding] options:@{NSDocumentTypeDocumentAttribute : NSHTMLTextDocumentType} documentAttributes:nil error:nil];

[self.textView setAttributedText:myHTMLString];

This example code is run from a UIViewController whose self.textView is an IBOutlet to a UITextView in the user interface. And here’s how it looks in the Apple TV simulator:

HTML rendered on the Apple TV simulator

Granted, this is a far cry from a fully-functional web view. I’m sure it won’t serve the needs of all developers who currently rely upon UIWebView or WKWebView, but I expect that in some cases it will be a valuable workaround to the otherwise total omission of support for rendering HTML on Apple TV.

NSURLSession Authentication Challenge Disparity

Thanks to a bunch of my networking-related unit tests failing on 10.11, I came to the conclusion that NSURLSession’s authentication challenge mechanism changed from 10.11 with respect to the way HTTP Basic Auth challenges are handled.

In 10.10 a data task that is created for a resource protected by HTTP Basic Auth will result in a callback whose protection space method is identified as “NSURLAuthenticationMethodDefault”, while in 10.11 the same code accessing the same resource yields a protection space method “NSURLAuthenticationMethodHTTPBasic”.

The problem here is that existing challenge-handling code may have been written to handle the 10.10 behavior, looking for HTTP Basic Auth challenges like this:

if ([[challenge protectionSpace] authenticationMethod] == NSURLAuthenticationMethodDefault)
	// Handle the challenge

While on 10.11 the “Handle the challenge” code will never be reached, so this shipping code will fail to function.

I think a robust workaround (that unfortunately requires re-compiling and re-shipping) is to test HTTP authentication challenges for either NSURLAuthenticationMethodDefault or NSURLAuthenticationMethodHTTPBasic, and treat them both as equivalent.

I filed this as Radar #21918904, and wrote a message in the developer forums in case people want to discuss the issue or the merits of various workarounds.

WebKit Hacking From The Bleeding Edge

As the developer of an app that depends heavily upon Apple’s WebKit technologies, I have often been grateful that the software is open source. It is by no means easy to wrap one’s head around, but when faced with a vexing problem, I can browse, even build and run a custom copy of WebKit on my system, to step through code and try to reason more clearly about its behavior. I’ve even filed my share of bug reports and patches.

While I am very interested in the evolution of WebKit, I am even more concerned with the evolution of OS X. For this reason, I typically install OS X beta releases far earlier than many of my colleagues. This gives me the opportunity to work day to day with the latest changes coming from Apple, and makes it that much more likely I will spot issues with my apps, concerns with the OS, etc., before my customers do.

As an open source project, I initially believed I could build and run WebKit wherever I choose. After all, isn’t that what “open source” is supposed to be all about? But ah, there’s a catch. At least when it comes to building and running WebKit on OS X releases, there is a dependency on a small, binary-only static library which provides key system-specific linkages to WebKit. Usually this binary is added to the open source project around the time the system release goes public, but not much sooner.

The long and short of it? If you want to build WebKit and you don’t work at Apple, you need to do so from publicly released versions of OS X.

For years, I have found this personally annoying, but also philosophically distasteful. It seems like a problem for Apple, too: it’s in their best interest to have as many WebKit developers as possible staying up to date, building the latest versions, testing, submitting patches, etc. And it’s in their interest to have as many OS X developers running the latest betas of the OS, providing feedback, preparing their apps for the public, etc.

A single developer, with a single Mac, running a single installation of OS X cannot simultaneously be a diligent, interested WebKit developer and a dedicated OS X beta tester. This seems like a problem to me, so I finally reported a bug. Radar 21703162: “Beta OS X releases should facilicate building/running WebKit from source.”

Predictable Date Formatting

Note: see caveats at the bottom of this post. Some of my conclusions in the body of this post are wrong and motivated by a misunderstanding of NSDateFormatter’s documented behavior. I’m leaving the post here for reference because I still think it could help somebody trying to understand similar behavior in their own app, but don’t take the griping too seriously…

Apple’s NSDateFormatter class supports a method of converting a date to a string by use of a date format string. For example, the date format string I use in MarsEdit to supply dates in ISO8601 format to blog servers:


That “HH” is supposed to reflect the hour as a zero-padded number between 00 and 23. And it does, or at least it has, ever since I started using this formatting string in MarsEdit eight years ago.

Starting very recently, I think with 10.10.3 (Edit: nope, not new after all, see end of post), NSDateFormatter may return a string formatted for the user’s 12-hour clock preference, and with a troubling “am” or “pm” component embedded within. So instead of a bona fide standard ISO 8601 date for the above format, MarsEdit is now prone to receive something like this:

20150526T1:58:42 pmZ

Oops! And Ugh! The whole point of using NSDateFormatter’s dateFormat string, I thought, was to specifically generate strings that defy the user’s preferences, but that comply with a very specific set of rules. In fact, Apple encourages using date format strings in their documentation:

There are broadly speaking two situations in which you need to use custom formats:

	1. For fixed format strings, like Internet dates.
	2. For user-visible elements that don’t match any of the existing styles

Yes, internet dates! Thank you. Well, no thanks, I guess. The current documentation also goes on to offer some caveats, particularly with respect to iOS, where I guess users have been empowered to override the 12/24-hour clock setting for longer than they have on the Mac. And in general, they warn:

Although in principle a format string specifies a fixed format, by default NSDateFormatter still takes the user’s preferences (including the locale setting) into account.

The specific scenario where this crops up for me is if the user has set their Mac’s region to one that defaults to 24-hour time, but has then specifically chosen to uncheck the 24-hour time option:

Language Region

The behavior doesn’t occur, for example, if the user’s region defaults to 12-hour time as it does in the United States. It only occurs when a region’s defaults have been specifically overridden.

If you want predictable behavior from NSDateFormatter, you must set an explicit NSLocale on the formatter before requesting any string generation. I’m not sure it matters which locale you set, the key seems to be setting it to anything but the default to avoid this strange deference to the user’s default settings.

I’ll be fixing this by setting the locale on the NSDateFormatter to “en_US” because, being the very locale that my Mac is most often configured to use, I’ll be more likely to notice if the workaround stops working at some point in the future. I reported a bug (Radar 21105874) because it seems to be there should be a more straight-forward means of expressing to NSDateFormatter that you want to perform a very literal conversion, one that is guaranteed to not take into consideration any user-provided customizations of date and time formatting.

Hopefully this post will help other developers notice and repair the faulty handling of date strings in their apps, before too many of your customers run into the problem first!

Update: Many thanks to several people on Twitter noting that Apple specifically recommends using the “en_US_POSIX” locale for this purpose. I am still a bit annoyed that the behavior changed out from under me, but it sounds like setting the locale explicitly to this computer-y locale is the right solution for the long term.

Update 2: Well I made a few wrong assumptions before writing this post. After further testing I’ve confirmed the problematic “new” behavior is at least the case in 10.9.4 and possibly earlier as well. I’m now inclined to think this has been my bug all along, but I still think I’ll file a bug with Apple encouraging them to update the documentation to stress that setting a locale on the formatter is important.

Update 3: It turns out the documentation goes into some detail about the need to specify a locale, but I overlooked it because it was in a section about “parsing date strings” (not what I’m doing here). I filed Radar 21115452, requesting better documentation about the need to set a locale in the section pertinent to either parsing strings or generating them.

Storyboard To Nib And Back

At some point along the way Xcode has consolidated the “Main Storyboard” and “Main Interface” fields pertaining to storyboard and nib files into a single “Main Interface” field that simply updates whichever of the pertinent Info.plist fields Xcode thinks you are working with.

The problem is that if you switch from storyboard to nib or back, then the value of the Info.plist entry is changed, but the key is not updated to reflect whether the new value is either a storyboard or a nib.

I’ve reported Radar 20954053 to Apple, requesting that Xcode should intuit from the file extension of the file named by “Main Interface” whether the Info.plist should advertise a storyboard or a nib.

In the mean time, if you switch from storyboard to nib or back, you need to manually update the Info.plist key to match: UIMainStoryboardFile if you’re using storyboards, or NSMainNibFile if you’re using nibs.

Open URL From Today Extension

A friend of mine mentioned in passing that he was having trouble getting an obvious, well-documented behavior of his Today extension to work … as documented. According to Apple, a Today extension should use NSExtensionContext when it wants to open its host app, e.g. to reveal a related data item from the Today widget, in the context of the host application.

A widget doesn’t directly tell its containing app to open; instead, it uses the openURL:completionHandler: method of NSExtensionContext to tell the system to open its containing app.

They even cite one of their own apps as an example:

In some cases, it can make sense for a Today widget to request its containing app to open. For example, the Calendar widget in OS X opens Calendar when users click an event.

The idea is you should be able to use a simple line of code like this from within your Today extension. E.g., when a user clicks on a button or other element in the widget, you call:

[[self extensionContext] openURL:[NSURL URLWithString:@"marsedit://"] completionHandler:nil];

Unfortunately this doesn’t work for me, for my friend, or I’m guessing, most, if not all people who try to use it. Maybe it’s only broken on Mac OS X? I was curious, so I stepped into the NSExtensionContext openURL:completionHandler: method, and observed that it essentially tries to pass the request directly to the “extension host proxy”:

0x7fff8bd83b03:  movq   -0x15df0b7a(%rip), %rax   ; NSExtensionContext.__extensionHostProxy

But in my tests, this is always nil. At least, it’s always nil for a Today widget configured out of the box the way Xcode says it should be configured by default. So, when you call -[NSExtensionContext openURL:completionHandler:] from a Today widget on OS X, chances are it will pass the message along to … nil. The symptom here is the URL doesn’t open, your completion handler doesn’t get called. You simply get nothing.

Getting back to the fact that Apple used Calendar as their example in the documentation, I thought I’d use my debugging skills to poke around at whether they are in fact calling the same method they recommend 3rd party developers use. If you caught my Xcode Consolation post a while back, it will come as no surprise that an lldb regex breakpoint works wonders here to how the heck Apple’s extension is actually opening URLs. First, you have to catch the app extension while it’s running. It turns out Today widgets are killed pretty aggressively, so if you haven’t used it very recently, it’s liable to be gone. Click on the Today widget to see e.g. Apple’s Calendar widget, then quickly from the Terminal:

ps -ax | grep .appex

To see all running app extensions. Look for the one of interest, ah there it is:

56052 ??         0:00.29 /Applications/

That’s the process ID, 56052 in this case, at the beginning of the line. Quickly click the Notification Center again to keep the process alive, and then from the Terminal:

lldb -p 56052

If all goes well you’ll attach to Apple’s Calendar app extension, where you can set a regex breakpoint on openURL calls, then resume:

(lldb) break set -r openURL
(lldb) c

Now quickly go back to the Notification Center, and click a calendar item for today. If you don’t have a calendar item for today, whoops, go to Calendar, add one, and start this whole dance over ;) Once you’ve clicked on a calendar item in Notification Center and are attached with lldb, you’ll see the tell-tale evidence:

(lldb) bt
* thread #1: tid = 0xd1a4d, 0x00007fff87f22f1f AppKit`-[NSWorkspace openURL:], queue = '', stop reason = breakpoint 1.8
  * frame #0: 0x00007fff87f22f1f AppKit`-[NSWorkspace openURL:]
    frame #1: 0x00007fff9213f763 CalendarUI`-[CalUIDayViewGadgetOccurrence mouseDown:] + 221

So Apple’s Calendar widget, at least, is not using -[NSExtension openURL:completionHandler:]. It’s using plain-old, dumb -[NSWorkspace openURL:]. And when I change my sample Today extension to use NSWorkspace instead of NSExtensionContext, everything “just works.” I suspect it will for my friend, too.

I’m guessing this is a situation where the functionality of Today extensions might be more fleshed out on iOS than on Mac, and the documentation just hasn’t caught up with reality yet. There are a lot of platform-specific caveats in the documentation, and perhaps one of them should be that, for the time being anyway, you should use NSWorkspace to open URLs from Mac-based Today extensions.

Yosemite’s Dark Mode

If you’re a Mac developer you’re no doubt feeling that restlessness that comes when a major new OS release is nigh. Mac OS X 10.10 Yosemite has been cycling through “GM Candidate” releases for the past couple weeks, and many people seem to think it’s likely to be released to the public later this month.

One of the big user-facing visual changes is an optional “dark mode,” accessible from the General tab of System Preferences. When a user ticks this on, high level UI elements such as the menu bar and dock adopt a different style of drawing which you can roughly characterize as being white-on-black instead of the default black-on-white Mac appearance.

One hiccup for developers of third party apps is if you have an NSStatusItem or other custom menu bar item with a custom icon, you probably designed it so that it looks good on the white or light default menu bar.

Unfortunately, Apple has not provided a sanctioned method for detecting whether the user has switched to “dark mode,” so it’s non-trivial to tune your art to suit each of the modes at runtime. Instead, Apple recommends that all such icons should be designed such that Apple can effectively color them as appropriate for the current mode.

Luckily it’s pretty easy to get this behavior for custom status bar icons. You probably already call -[NSStatusItem setIcon:yourImage] with your custom image. Now, just make sure to call -[yourImage setTemplate:YES], and you’re done. The only caveat I would add here is that Mac OS X 10.9 and earlier do not seem to respect the “template” attribute when drawing status items, so I think the safest bet is to check for 10.10 at runtime, and omit the call to setTemplate if you’re running any earlier system:

BOOL oldBusted = (floor(NSAppKitVersionNumber) <= NSAppKitVersionNumber10_9)
if (!oldBusted)
	// 10.10 or higher, so setTemplate: is safe
	[myIcon setTemplate:YES]

Now your status item icon looks great on 10.10, where in fact its coloring may even be slightly altered in light mode, and in 10.9, where it looks, well, like it always did. Update: thanks to Rick Fillion and Will Cosgrove for explaining that my problems on 10.9 are probably because my image is not designed right for use as a template. I’ll leave the solution to that as an exercise for the writer.

Unfortunately, this promise does not hold true for regular NSMenuItem items that are installed at the highest level in the menu bar. These are relatively uncommon, but for example you might find some apps with a gear icon, a script icon, or other similar graphic in lieu of a text-based menu title. When an icon is supplied to such a menu item, the template nature is not meaningfully respected in dark mode, so the icon draws more or less as-is, and is likely to almost disappear because of the lack of contrast. If you happen to be running 10.10 you can witness this problem by running iTunes and seeing that at least one script is in ~/Library/iTunes/Scripts. Its script menu icon appears right next to the “Help” menu.

I reported the issue to Apple and it came back as a duplicate. As of the latest 10.10 GM candidate, it has not been fixed, but I got a reassuring tweet from Apple’s own Eric Schlegel today:

So in summary, if you use icons as the “titles” of menus either inside or outside of the status bar area of the menu bar, be sure to call setTemplate:YES on it when running on 10.10. If you happen to have a menu bar icon affected by the bug I reported, I recommend creating a test project that installs an NSStatusItem with the same icon, so you can get a sense for how it’s going to look in dark mode when its template nature is suitably handled.

What To Do About Code Signing

I wrote about the confusion arising from Apple’s poor communication about new code signature requirements, and then just earlier today I wrote about the revelation that many apps have been reprieved by an Apple whitelist.

I tend to write long, so let’s cut to the chase: what do you need to do if you are a Mac developer who ships software directly to customers or via the Mac App Store?

  1. You must ensure your next software release is signed with a Version 2 code signature. The easiest way to do this is to build and sign your product on Mac OS X 10.9 or later.
  2. You must test your existing, published apps to see that they can be downloaded and opened without issue on 10.9.5 and 10.10. To be safe, try to test once from a machine/install that has never seen the app before. If you’re concerned, read the details in my previous posts to assure yourself that your existing app was whitelisted.
  3. If your existing app does not open or in particular if it receives an “obsolete resource envelope” assessment from the “spctl” tool, you must either release a new version of your app signed with a Version 2 code signature, or re-sign your existing app. Otherwise, people who download the app will be greeted by a warning that the software is “not trusted.”

That’s it, folks. Everybody has to start signing with the modern code-signing infrastructure. In the interim, there’s a good chance your app has been whitelisted to operate as usual during the transition, but that courtesy will probably not extend to your next release.