ARC and copy

Like many of you, I’ve recently starting coming to terms with automatic reference counting (ARC) in Objective-C. For the most part, it’s gone remarkably smoothly. The only hard part is remembering to not type autorelease!

ARC lets us get rid of the retain/release pairs in our code. But can you spot the bug in the following code?

@interface MyObject : NSObject

@property (copy) id ivar;

@end


@implementation MyObject

@synthesize ivar = _ivar;

- (id)initWithIvar:(id)ivar
{
  self = [super init];
  if (self != nil) {
    _ivar = ivar;
  }
  return self;
}

@end

The ivar instance variable is a strong reference, not a copy. Since I think it’s a bad idea to use accessors during -init the copy semantics defined by the @property are never used and ARC happily retains the reference instead of copying it. Also of note: the static analyzer doesn’t think there’s anything wrong with the code above, so you won’t see any warnings that you’ve screwed up.

In my case, this initializer led to a bug where several worker threads were modifying the same instance variable and, well, you know how that goes. The fix, as usual, was painfully simple:

    _ivar = [ivar copy];

It’s important to remember that ARC primarily affects how we use -retain and -release. As Matt Drance points out the way -copy works hasn’t changed significantly. Just because we can forget about typing “retain” and “release”, doesn’t necessarily mean that we can forget to type “copy”, too.

Updated May 4th, 2012: A Radar about the static analyzer not issuing a warning has been filed: rdar://11386493

iTunes Manglement

I think we can all agree that iTunes is in need of a major overhaul. So why isn’t it happening?

Apple has shown no fear of rethinking and innovating with the user interfaces that manage our own personal data. Both the iMovie and iPhoto apps are great examples of this: they’ve gotten much simpler to use over the years (especially as they’ve moved to the iOS platform.)

This makes me think that there may be another factor that’s holding back iTunes; and I fear that it’s contractual.

Much of iTunes functionality is based around content that Apple or the user doesn’t own. And as we all know, the media companies that own the content are particularly paranoid about how digital assets are managed. In the 10+ years that iTunes has been in existence, I’m sure there’s a tangled web of legal obligations that makes improvements a huge technical headache.

To give you an idea of how painful this must be, imagine being a developer at Apple and having to consult this before implementing or improving a feature in iTunes. And when you’re done wrapping your head around those conditions, make sure you have thought about restrictions in other parts of the world. Having fun yet?

Homebase

A lot of people I know and respect have been commenting on problems associated with the iPhone mute switch:

John Gruber – On the Behavior of the iPhone Mute Switch
Andy Ihnatko – Unmuting on The Mute Question
Marco Arment – Designing “Mute”
Guy English – Mute This

Both sides of the argument have valid points-of-view. This really is a situation with no right answer given the current mechanisms.

That got me thinking that there might be something missing that’s causing this ambiguity. I’ve come to the realization that this is a problem bigger than just alarms going off at inopportune moments. What we really want is for the devices in our pocket to behave differently depending on where they’re physically located.

Let’s imagine a new feature in iOS called “Homebase”. A user would be presented with a simple UI that lets them select a location that’s a “safe” environment. After the setup is complete, your Homebase would be recognized by GPS coordinates and/or available Wi-Fi networks. The important thing here is that the user gets to define where they feel safe with their device.

With that information developers can make smarter decisions:

  • Alarms that go off while the mute switch is on make noise at Homebase and just vibrate elsewhere. There’s no need to worry about alarms going off in public places (such as concert halls) and you won’t oversleep when you go to bed with a mute switch on.
  • The lock screen doesn’t need to display a Passcode lock at Homebase. People who use the Remote app with their Apple TV will no longer be annoyed by an unnecessary security precaution, nor will folks forget to turn their Passcode lock back on when they leave for the local bar (where they’re certain to get a Poopin’ tweet.)
  • Apps, like Find My Friends, could use cached Apple ID credentials at Homebase and avoid asking the user for them over and over and over and over again.

Of course, this feature is needed most by people who don’t even know the Settings app exists. It’s my opinion that if developers are careful with this additional knowledge about the user and device, default behavior can be adjusted appropriately without additional confusion. It’s analogous to the Energy Saver on the Mac: people don’t question why the screen dims when the power cord is removed because it just “makes sense”.

The examples above use Apple’s own apps, but the Homebase status would be useful for third-party developers, too.

If you’d like to see something like Homebase in iOS, please be sure to file a duplicate Radar.

Un-Trusteer-ed

The bank we use for our business account recently mandated the use of a product called Trusteer Rapport while accessing our information online. Although Mac OS X doesn’t have any problems with “increasingly sophisticated malware in the online environment”, I do need to periodically check our accounts and transactions so I proceeded with the installation.

The first warning sign was after starting the Installer: I was prompted for an administrator password indicating that this software wanted to run from protected areas of my system. Being a developer, I immediately dug into the installer scripts and configuration files to see that the app is placing items in the Rapport/bin, PreferencePanes, LaunchDaemons and LaunchAgents folders of the main system Library folder. The launch folders indicate that the software will be run whenever my Mac is restarted and will be able to do things a normal user would not (because of elevated permissions.)

I placed my security concerns aside as I need to access my bank website, so I went ahead with the installation. Afterwards, I was directed to a web page describing the new software.

Again, as a developer, my first thoughts were suspicious ones. From experience, I know that it’s not easy to modify Safari’s user interface in the way that Trusteer was doing. My guess that there would be a new, always active, background process was confirmed by the presence of “rooksd” in my process list.

However what happened next really opened my eyes. Safari crashed.

Of course that, in and of itself, isn’t the end of the world. But I was surprised to see a new library named RapportUtil1 while looking at the Safari crash report. It was pretty clear that the new Trusteer software caused the crash. But how?

As a longtime Objective-C developer, I know a thing or two about “method swizzling“. In a nutshell, this allows a developer to replace the functionality of code they don’t have direct access to (typically in the system or other frameworks.)

Seeing “_nsapplication_sendEvent_override” tells me that Trusteer is using this technique to change the behavior of Safari. The function that is being affected is -sendEvent: — the part of every Cocoa application where mouse, keyboard and other input is routed.

Method swizzling is a dangerous activity. You have to make assumptions about how some other code, that you’ve never seen, is behaving. You also need to think about how that code might change in future versions. There are extreme cases where this technique can be effective: overriding the default behavior of my web browser is not one of them.

It’s clear that the folks taking control of my browser aren’t as clever as they think. Do you see a common theme when you search Apple’s discussion forums for “RapportUtil1“?

Even more troubling is the method being overridden: every key press or mouse movement is first being sent to Rapport and then forwarded onto Safari. Since this happens often, the intruding software can do pretty much whatever it wants, whenever it wants. And remember that part of this package is running with elevated permissions in the background.

After mentioning my findings on Twitter, I got back some very interesting replies. Graham Lee (@iamleeg) pointed out that I’m not the first developer to question the technical merits of this software. But then Peter Hosey (@boredzo) dropped the real bomb. Trusteer tacitly admits to recording my password. That’s easy to do when you take control of -sendEvent:.

Essentially, my bank is asking me to install is a keylogger. Just so they can warn me not to use the same password on suntrust.com and playboy.com.

Hopefully, the engineers behind Rapport are smart enough to be using hashed passwords rather than clear text. And hopefully none of the personal information Safari has access to is being forwarded to the Trusteer servers. And hopefully they’re not recording how many times I visited playboy.com last month. But that’s beside the point, because as a closed source product, no one can audit their activity. That’s not true with Safari.

Oh, and there’s one other thing: the Rapport software isn’t supported on Lion. One of the tenets of method swizzling is to test your software early and often with any new release of the system or framework that it’s modifying. As a developer, you need to be proactive about fixing any problems that pop up in the code you are overriding. Not doing so is irresponsible and puts your users at risk. The last update for Rapport was in 2009.

(One could speculate that the new privilege separation architecture for Safari in Lion is causing Trusteer’s developers a lot of headaches. The other tenet of method swizzling is to remember that it’s not a matter of if your hack will break in the future, but rather when it will break and how painful it will be to fix.)

Needless to say, I have uninstalled this software and will never be installing it again. I would recommend this course of action to any end user.

But that leaves me with a problem: how do I access my bank’s website? I have three options:

1) Find another bank. This is a difficult choice, as there are many systems that are hooked up to this account: ACH transactions for sales via iTunes, bi-weekly payroll, automatic payments for services, etc. I’d also like to give SunTrust a chance to reconsider their position in requiring this software (they will be getting a copy of this report.)

2) Use the telephone. I can call the bank when I need the information. Sure they’ll get tired of hearing from me, and it will cost them more for customer service, but it’s their choice to require Trusteer Rapport.

3) Run the Trusteer Rapport software in locked down environment. Once it’s supported on Lion, it should be possible to create a virtual machine that that will only be used to access the bank website. Needless to say this is inconvenient, a waste of resources, and severely limits my ability take advantage of my bank’s services.

In closing, I’ll leave you with one final irony: I will never be able to access my bank’s website from what is arguably the most secure computing device in existence today. That’s because the iPad is not a supported platform. Apple only allows third-party applications to run in a secure sandbox where they can’t affect other applications or the operating system. What you’ve seen above is exactly the reason they’ve done this.

Great writing, terrible reading

Apple has recently released Xcode 4—a major part of this release is an overhaul of the user interface. Change in your development environment is always a bit disruptive, but overall I think the move towards a single-window environment that adapts to different working modes is a good thing.

But this post is not to debate these changes to the programming environment. Rather, I’d like to discuss the new documentation viewer and how it has become unsuitable for both Mac and iOS development.

Apple’s technical documentation has always been top-notch: well written with just the right amount of technical detail. Unfortunately, the documentation viewer that we use to read this valuable information has been declining in ease of use over the past few releases.

It has gotten to the point where frustration with usability overshadows the excellent content. The best way to describe these annoyances is by example: I often get the feeling that the writers who create this prose don’t understand how we use it. Hopefully, this critique will help Apple create a viewer that’s just as good as the information it holds.

A corrupt index

A developer coming from Xcode 3 will have a terrible first experience with the new documentation viewer. Any previously installed documentation sets are incompatible with Xcode 4. Methods that you know exist just don’t show up:

Search in vain

There are also problems with the Jump Bar navigation stack not being recorded correctly and the browsing history being unavailable (the back button isn’t available when it should be.)

Presumably, there is a corrupt or incompatible index. The workaround is to delete and re-install the documentation set, but this is far from obvious.

Since I currently have three different versions of Xcode installed (and will continue to use Xcode 3 for the foreseeable future), I’m wondering if this corrupted/incompatible index will continue to be a problem. Fingers are crossed, but at least now we know what to fix if it breaks.

Popup hell

When you hold down the option key and click on a symbol in Xcode, you see the following window:

Popup hell

For novices, this window has some utility—it provides a simple way for them to dig into what is probably unfamiliar territory (“What’s a UIWindow anyway?”).

The problem is that this window becomes a roadblock for experienced developers. We know damn well what a UIWindow is: we need to dig into the details of this important class. Maybe we want to know more about the rootViewController instance or look at some of the methods in UIResponder (because we know it inherits from that.) This helpful popup quickly becomes a hindrance.

In previous versions of Xcode, holding down the shift key along with the option key gave you a quick way to avoid this popup help. In Xcode 4, that shortcut is gone.

Considering that this feature can get in the way hundreds of times per day, this is truly popup hell.

rdar://9149588

No methods

Once you get the documentation index in working order and actually make it past the popup help, your next hurdle is to locate the information you seek. Let’s say we’re looking for some background on what happens when a new -rootViewController instance is assigned. We’ve got the page of documentation, but there aren’t any controls to show the methods for the UIWindow class:

No methods

Besides being a pain in the butt, this is wholly inconsistent with the behavior in the code editor:

Methods

(Note that typing “ro” is enough to select “rootViewController” in the code editor’s popup menu. That, followed by the enter key gets you to the code of interest.)

From a developer’s point-of-view, the header files and the documentation page go hand-in-hand. Make the UI affordances the same and we don’t have to think about whether we’re looking at code or the words that describe it.

With a little more digging, you’ll find that you can get to the rootViewController documentation with the Jump Bar. Unfortunately, it takes a lot more effort than in the code editor: you have to click on the class name, and then move the mouse until the subcategories appear. Choose “Instance Methods” and wonder why rootViewController isn’t there. Then move the mouse back and try Properties.

Bingo (but you don’t feel like a winner.) And forget about navigating these lists quickly and easily with the keyboard as you can with the code editor.

rdar://9149638

Unmanaged complexity

Our final navigation problem is reading chapter-based documentation. These are the crown jewels of Apple’s developer documentation. Titles like The Objective-C Programming Language, iPhone Human Interface Guidelines, and the Cocoa Fundamentals Guide are essential reading for all developers, both beginner and advanced. As I began learning about Xcode 4, of course I turned to the excellent User Guide.

These guides typically span many chapters when sections that cover a wide range of topics. And this is how you navigate through those chapters:

Unmanaged complexity

Managing complexity, indeed.

The pity here is that someone in developer documentation has forgotten that a Table of Contents tells a much more important story than the individual chapters. A roadmap lets you visit the destinations efficiently.

To get an idea of how painful this is, try finding the recommended Singleton implementation in the Cocoa Fundamentals Guide using the Jump Bar. I’ll wait. (For extra credit, count how many menus you open in the process.)

Of course the documentation viewer has a search function, but even that’s a bit laborious because you have to click on a lot of disclosure triangles to find the right item in the results. Why aren’t the relevant results opened automatically? (And, yes, option clicking the disclosure triangle can be used to achieve this goal, but the question still remains: why isn’t this the default action?)

Updated March 29th, 2011: Matt Neuburg has discovered that for some documents, search results don’t show where your term occurs; you’re shown a higher-level page, but not the actual page.

The root of the problem here and with the method names in the class documentation, is that a deep hierarchy is too hard to navigate. Present the information in a single list and it becomes much more useful. Imagine how bad the code editor navigation would be if it presented a hierarchy based upon classes, properties and methods. It’s flattened into a single menu for a reason: and those same reasons exist in the documentation viewer.

The Jump Bar is a great addition to Xcode, but it’s true power lies in having a predictable end point. With code, that end point is a function, property or method. With documentation, that end point is elusive: it varies depending both with the type and the structure of the documentation you’re viewing. And that’s a real problem when you’re looking for something.

rdar://9149683

ePub, not PDF

While we’re on the subject of this long-form documentation, why isn’t more of it available in the ePub format used by iBooks? It’s pretty safe to assume a huge majority of Mac and iOS developers have an iPad and like to use it for technical documentation. Searching for “Apple Developer Publications” in iBooks results in only six books. That’s a great start, but there is still a lot of documentation available only in PDF.

PDF is, of course, an option for iBooks. But turns out to be unsuitable because there is no back button. If you click a link in the PDF file, it’s a one way proposition. And for technical documentation, that’s a deal killer.

ePub also has the advantage of better font control and image viewing.

rdar://9149845

Some good news

Fortunately, it’s not all bad news. This new version of the documentation viewer seems to keep track of its place on the page much more reliably than in the past. Gone are the days where hitting the back button put you back as the top of the page (instead of the method or property you were looking at previously.)

This one simple fix will save developers a huge amount of time. Thanks!

Ingredients

This situation with the Xcode document viewer has gotten so bad two developers, Alex Gordon and Jean-Nicolas Jolivet, have taken matters into their own hands. This ultimate workaround is an application called Ingredients.

Ingredients parses the HTML files used by Apple’s own viewer and persists the information with Core Data. The result is quick access to the documentation you need with advanced options to filter and sort to your liking. Recent work by Troy Gaul added an item to the Services menu so a keyboard shortcut can be created to view the selected symbol from any text editor (include Xcode.)

If the problems mentioned above affect you adversely, take a look at this alternative documentation viewer. And please take a moment and file duplicate bug reports using the Radar links above. This is the best way to give Apple an idea of how much this is affecting our daily work. Thanks!

Updated March 22nd, 2011: The developers of Ingredients are now accepting donations.