Autorelease the Hounds

I’ve been thinking about weak references in ARC.

Let’s say I’ve got a new application model layer, for describing urban transportation infrastructure:

Diagram of a tree of objects

The topmost object is an “Urban Transportation” object, which owns a list of city objects (in this case, “New York” and “San Francisco”). Under each city object are the kinds of transportation in that city, such as cars, buses, and airports (planes). Each object owns the things underneath it and is responsible for disposing of them (releasing them) when they’re removed. Good so far.

The odd man out in the diagram above is the flight object, “Flight 2077”. It’s owned directly by the top-level object, for lack of anyone else to provide direct ownership. But the two airports underneath the “New York” and “San Francisco” objects each have what I’ll call a “cross-tree” reference to it, since it’s a flight between those two cities.

What should those cross-tree references look like?

In retain/release, you have two options, and they’re both bad. You could use unretained pointers. Those have the advantage of not creating retain cycles, but they’re dangerous because they’ll continue to refer to the flight object even after it’s been released.

Or you could use retained pointers and add what I’ll call an “invalidate” method to the flight. “invalidate” methods rely on the fact that, even when the retain cycle hasn’t been broken yet, you know from your application’s logic when your object should go away. At that time, you call “invalidate” on it, and then it breaks the cycles for you. In this case, the flight object would have to contain its own pointers back to the referring airports, and be able to tell the airports to remove their pointers/retains to itself. The more classes in your model that can have cross-tree pointers, the more “invalidate” methods you need, to the point where you’d probably just want to make it a mandatory protocol. Lots of extra logic, easy to get wrong.

In garbage collection, you’ve got a better option. You can use weak pointers. That way, once all the strong references are removed (in this case, the reference from the “Urban Transportation” object), the weak references in the airport objects would be set to nil, and the flight object would be deallocated. Easy peasy. You could still use an “invalidate” method here, but it’s not necessary. (Though it’s still a good idea for releasing other sorts of resources under GC without employing a finalize method, which Apple discourages.)

In ARC, you can also use weak pointers, in exactly the same way you use them in GC. But is that an undesirable amount of overhead? The whole point of ARC is that it’s fast and immediate. But the more weak pointers you use, the more you’re forcing the system to keep track of all your pointers and objects, in a way very reminiscent of GC, and not at all like the rest of ARC, which just drops in just the right number of invisible retains and releases at compile time and calls it a day.

My gut feeling here, though, is that the overhead won’t be that much unless you’ve got an overwhelmingly large number of objects. Won’t know till I try it!

7/15/2012 Note: The title is actually taken from one of the rejected episode titles of the latest Edge Cases episode, which we recorded before I posted this, even though the episode itself was only released afterwards. Wolf’s thoughts definitely informed my final edit of this post. That title actually came from Vincent Gable’s tweet, however.

Put It on My Tab

In the Edge Cases1 episode “My First Xcode 4 Rant”, I talk about my frustrations dealing with the Xcode 4 window.

Apple has a response, kind of, in their WWDC 2012 video “Working Efficiently with Xcode”.2 There, (amid a lot of other helpful tips) they talk about “task-based tabs”. To get around the fact that Xcode makes no effort to configure its helper views for the kind of document you’re editing, they recommend manually creating customized layouts in their own tabs: a design tab for xibs, for example, where the utility pane is always present.

I’ve used Xcode 4’s tabs, and they don’t work for me.

For one, it’s clunky to have to make sure you only open certain documents in certain kinds of tabs. I want to switch between documents quickly. This usually means using the filter in the navigator pane to find the right file, then selecting it there, then using file history to go back and forth between that file and my previous files. All good stuff. But if I have to intermix that with, OK, now, you need to remember to go over here to open this file, well: by the time I remember to do that, I might as well just use the keystroke shortcuts to open and close the utility pane each time, no?

But the worst is Command-W.

You know what happens, after you lovingly spend minutes and minutes configuring your special tab with exactly the right spacing and exactly the right helper panes? That’s right, you accidentally hit Command-W, because your fingers have been trained for years to dismiss files this way. And when you do that, all your painstaking work is gone in an instant. Poof! (Actually, there’s no animation.) No undo. It’s just gone.

After doing that enough times, you stop spending a lot of effort configuring tabs.

But you still don’t escape, because even if you just have one working tab, you inevitably start arranging that tab how you want it to look. And if you have a second tab of any sort, such as the Debug tab that’s recommended in the session so that you don’t have to keep showing and hiding the debugger pane, Command-W kills your first tab dead.

And if you have no tabs, Xcode 4 closes your whole window, so you can’t even get used to one shortcut for views and one shortcut for windows. Frustrating.

And even if all that didn’t bother you that much, remember Rule Number 4 from “Would They Call It iCode?”: No UI Fiddling! Needing to manually set up your own tabs is the definition of UI fiddling. It’s as if Apple is saying, Go on, live in the trees, we recommend it! But instead of providing you with a treehouse, they just provide you with a bunch of lumber and nails. (And your house falls apart if you close the door too hard.)

Edit: OpenRadar 1814402

Edit 2: Inspired by Ole Begemann’s comment, I found this post by Brian Webster describing how he used Xcode custom behaviors (with keyboard shortcuts) to create custom tabs. Lots of good details. Don’t have time to address this in depth right now, but wanted to get it out there.

Final edit: Imagine every time you open a new file, Xcode’s window autoconfigures itself to the default layout for such a file (which you can change in prefs). For xib files, it shows the utility pane; for .m files, it hides the utility pane, but shows the assistant pane with the associated .h file. And further: it remembers any custom configuration for individual files, so if the last time you had Foo.m open, you also had its associated xib file open, it replicates that as well.

Custom actions can be very powerful. If I’d actually finished watching the “Working Efficiently” session before I wrote this post, I would have found out exactly how to set them up. They can “fix up” the layout options to an existing file, for example; you don’t need to create a new tab. Such things can help me out quite a bit.

But I still think it’s doubling down on the wrong approach. Too many extra steps you’ll have to do over and over, too much manual configuration of things Xcode should already know. And that’s all I have to say on the matter for now.

 

1. Note: despite the URL, which we chose because it would be laughable to expect “EdgeCases” to be available in 2012, the show is called “Edge Cases”, not “The Edge Cases Show”. Like, y’know, “Bono”, or something.

2. No direct link, but go to https://developer.apple.com/videos/wwdc/2012/, sign in, and search for the title. And if the website verbiage and my Twitter compatriots are to be trusted, you don’t even need a paid account to watch it.

How Long

I made a chart showing how long it would take, at current growth rates1, for Apple to sell an iPhone to every man, woman, and child on the planet:

Chart showing Apple iPhone exponential sales growth

Per Wikipedia’s estimate of world population (about 7 billion), it would take about five years.

(Uses information from the post “iPad versus iPhone versus iPod” from AAPLinvestors. PDF file here, table data as PDF here.)

 

1. Using HUUUUUGE amounts of approximations and simplifications, I know. Assumes projected growth rate of 20%, which from the data for the past several years, seems like a decent assumption.

Caveat-Slash-Manifesto

It has occurred to me, since I started writing and podcasting in more depth about Xcode 4, that a caveat is in order.

It’s not a secret that I worked at Apple for a bunch of years. It’s been in my About page on this blog since the beginning.

What I haven’t said publicly is that I worked on Xcode itself—the application—for all those years.

Is that a conflict of interest? Am I going easier on it because some of my code might live on somewhere in the newest version? Am I criticizing it more harshly as an ex-employee?

Hopefully, none of the above.

I did ship some features in Xcode 3. But I can say that, with one or two very trivial exceptions which I’ll avoid talking about here, there are none of my fingerprints on Xcode 4.

In my mind, that frees me to discuss it like any of you would.

Well, maybe not exactly like you would; I’ve been thinking a whole lot about developer tools, so I have more of an interest in exploring in detail the highs and lows of Xcode 4 than most other folks. And, unfettered either by personal involvement or Apple’s shroud of secrecy, I intend to continue doing just that.

But I figured you should hear about my…particular background now rather than later.

Why Did It Have to be Mimes? (Shakes Fist)

I’ll freely admit the the first reason the Edge Cases podcast isn’t on iTunes is because I forgot to submit it on Sunday night.

But the second reason is more interesting. When we first tried to submit our Feedburner feed1 to iTunes, Apple sent us an email a few minutes later saying, sorry, there had been an error. But they didn’t tell us what error.

Feed Validator was more helpful, but only to a point. It told us that we should use UTF-8 encoding if we wanted to submit to iTunes. But we were specifying UTF-8 in our RSS file. It turned out, FeedBurner would only respect that setting if the RSS file MIME type was properly set to text/xml, which ours was decidedly not. Instead, it was—oops!—set to image/jpeg. (Hilarity did indeed ensue.)

So we fixed that, and Feed Validator said we were good, and we submitted again. Bzzzt. Another email from Apple saying there was an unspecified problem.

After another hilarity break, it occurred to us that if there was a problem with the MIME type for one of the files, maybe there were problems with some of the other files as well. Y’know, unimportant ones, like the MP3 files.2 Yup, they were also set to image/jpeg. Once we changed them, the feed was accepted by Apple.

And now it’s in…moderation, I guess? I wonder if it’s the same folks who review the apps….

 

1. Which in the meantime you can use directly in iTunes, by the way. Advanced -> Subscribe to Podcast… -> paste in the feed URL.

2. I suppose it could have been the logo file, which was a PNG file, not a JPEG file, but I’m dubious. And I’m not resubmitting in order to find out.

Livin’ on the Edge

Back from WWDC? Great!

That means it’s time for you to subscribe to Edge Cases, a weekly podcast about (mostly Apple-related) software development, by myself and Wolf Rentzsch:

http://www.edgecasesshow.com

Just like WWDC, WWEC (Whole Week of Edge Cases) will last Monday through Friday, one episode each morning from our 5-episode backlog, including such gems as “Dot-Mom and Apple Pie” and “Would They Call It iCode?”

Then, once you’re all caught up, we’ll release an all-new episode over the weekend.

We hope you like it!

Fleeting

I had a problem recently with Core Data transient properties, my own fault.

What I hoped they would be was full-fledged members of the database which just happened not to be saved to disk.

What they actually are is glorified instance variables. The trouble with using a custom subclass ivar is that its value is only present in the specific object you set it on. If you get a different object representing the same entity, say from another context, it won’t have that value. These can lead to lots of problems.

I wrote a sample Mac app, available on github, that demonstrates the problem. Here’s me setting the “name” property for a couple of entities:

Here’s me using the “Refresh” button to use a second managed object context to retrieve those same entities:

Names are gone! (And pointer values are different.) If I change the name attribute to not be transient, the names are preserved, even though the pointer values are still different:

I’m sliding over a lot of details here. This post by Jakob Stoklund Olesen has more information, but since it’s from 2007, it may be out of date. (It’s still the first google hit for “Core data transient properties”, however.)

This

From Brent Simmons’s blog inessential:

So here are my two pleas:

  1. Use dot notation for properties.
  2. Do not use dot notation for non-properties.

This. So much this.1

I am in the process of imposing these rules, property by property, in a codebase I have recently inherited, for exactly the reason Brent suggests:2 avoiding the need for multiple searches in order to find all the usages of a single thing.

Future versions of Xcode could help with this, but in lieu of clang-y goodness, it’s amusing to me that Brent and I hit on exactly the same way of threading the needle.

Are there more of us out there, muttering under our breath during our find/replace sprees?

 

1. My first thought here was, “But an Objective-C blog post should be called Self, not This.” So I am sharing that thought with you.

2. Well, also because I love organizing things.

How I Learned to Stop Worrying and Love the Podcast

There are three ways I interact with y’all on the Internet.

The first, Twitter, is delightfully immediate and informal, and I use it many times a day. (It’s really gonna suck if Twitter goes evil.)

The second, blog posts, seems like it should be close to Twitter in terms of immediacy and informality. But the more I write, the less this seems to be the case.

The blog posts I enjoy most are the ones that get to the heart of the matter quickly and simply. They give me the desired Ah-ha! moment and, boom, they’re done. (With, however, a level of detail that Twitter can’t provide.)

But writing posts like that…the good bloggers make it look easy, but it’s not. I myself have only written a smattering of random posts. But it’s never really felt like I’ve gotten better, or that I’ve developed a theme. Like my blog is really about something.

The third, podcasts, is something different again. Quite different.

It’s the only one with a schedule, so there’s a more of a rhythm to it than tweets or posts. (More practice.)

It can feel more immediate, more lively than a blog post, because you hear the host’s intonation. More emotion comes through. It’s easier to incorporate listener responses, like a Twitter thread. It’s fun.1

And because it’s an actual chat, rather than text on a page, the same rules don’t apply. You can go on long-winded tangents. You can get to the heart of your topic sideways, or even miss the critical point and fill it in the next week. You can make mistakes and laugh about it. If you’re enjoying yourself, your audience will too.2 And week by week, you can get a little better, hone your presentation skills, discover the topics you really shine at.

Basically, it’s one route to becoming a good blogger, if blogging alone isn’t cutting it.

 

1. And did I mention show notes? I really like putting things into the show notes.

2. Or they’ll stop listening. Same diff.