Out of Context

Twitter’s been having a discussion about tech job interviews recently: you can see my contributions here, here, here, and here.

For the tl;dr crowd, my take is that interviews are extremely difficult, and so you (and I) should have some empathy.

A while ago, I did a bunch of interviews for a junior iOS developer. I gave them what is apparently a quite common exercise: in a simple iOS app, get some JSON data from a server and use it to populate a table, including, for each entry, a link to an image file to download separately.

I just made such a project, called Numbers, available here.

When you first run it, it shows a table filled with entries 1-20, where the brightly-colored number icons are each loaded separately.

A button to the right of the navigation bar is labeled “Wrong”, meaning you’re currently using the image loading implementation that’s incorrect.

If you scroll to the bottom of the table quickly, you’ll see that initially, the rows you uncover will be temporarily populated with incorrect icons:

Screenshot of "Numbers" application table view, scrolled to bottom, with rows 16 through 20 having incorrect icons 2 through 6.

That’s because, in the incorrect implementation, the async network calls insert the loaded images into the cells that originally requested them.

But, as Everyone Knows, cells in UITableView are reused when you scroll, which means by the time the network calls finish, the original cell might be in use for at a different row, and it shouldn’t display the original row’s contents.

Instead, the network call for an image should update the cell that currently represents the row.

If you tap the “Wrong” button, it will change to the text “Right”, and that’s how the application will behave when it reloads the table. Scrolling quickly to the bottom of the table won’t result in erroneously populated images anymore.

When I was interviewing, if the interviewee said they knew table views, I would give them this exercise, and would consider them not worth hiring if they made that rookie mistake.

Nowadays, it’s clear to me that this is a Gotcha! question like any other.

Instead of it being a question about how they think, how they solve problems, it requires a very specific piece of information you either have it your head at that moment, or you don’t.

In a recent interview where I was debugging a problematic table view implementation, I failed to recognize a similar incorrect image loading mechanism — until nudged to do so by the interviewer. I just didn’t see it. If that interviewer had been as quick to judge as I had been in the past, I wouldn’t have gotten the job.

As a final note of curiosity, you might notice that, in the Numbers project, I reset the NSURLSession each time before reloading the table view’s contents. That’s because NSURLSession has its own cache of network call results, and if I didn’t reset it, you would only be able to reproduce the “wrong” behavior the very first time you tried it. Every subsequent time (including across app relaunches), the images would “load” instantaneously from the cache.

While I would never recommend shipping the wrong implementation, even if you did, these days, Apple’s frameworks would mitigate its impact.

Diverse Rolling

Two years ago, I took the OPML file from Brent Simmons’ inessential post “Blogs by Women”, threw it into my RSS reader, and magically had 30+ new blogs to read.

Here are the favorites of mine that are still around and active.

Erica Sadun (Twitter)
I’ve known about Erica’s work since the 2013 Edge Cases episode “Rectangles on a String”. (I even know how to pronounce her last name, even if she does pronounce tuple wrong.) Her blog updates several times a week, often about some detail of Swift development. She’s written a bunch of books, mostly focused on developers, and one book on Swift.

Accidentally in Code, by Cate Huston (Twitter)
Most delightful find for me personally. She talks about a variety of issues in the tech industry, including managing, as I’ve previously mentioned.

Becky Hansmeyer (Twitter)
From her own description, her blog is “my own little place to comment on Apple & general technology news, as well as what it’s like to be a novice developer with no prior programming experience.” Her tag line is “100% grass-fed Swift”.

Natasha the Robot (Twitter)
Helpful posts on iOS/watchOS and Swift topics. Natasha is the organizer of the try! Swift conference, and frequent speaker.

Julia Evans (Twitter)
Detailed, explanatory posts on a variety of tech topics. Very motivational! Not iOS-related, however.

And finally, a great blogger who’s been very active recently who’s not on the list:

Stephanie Hurlburt (Twitter)
Graphics developer and entrepreneur, who posts about a variety of aspects of the tech industry, some of them quite personal.

Enjoy!

Point of No Return

I found an interesting (to me) aspect of Swift/Objective-C interactions this week.

Take this Objective-C method:

+ (nullable NSData *)dataWithString:(nullable NSString *)string error:(NSError **)error

It uses the standard Apple pattern of having both a return value and an error. (I left out the error’s nullability annotations for brevity, as Apple always assumes them.)

In theory — and, if I’m remembering correctly, according to Apple guidelines — first, you’re supposed to check if the return value is invalid. Only once you’ve verified that it’s invalid should you check to see if there’s an error.

And as far as I’m been aware, there’s never been any assumption that you’ll get an error. That’s why, throughout your Objective-C code, you always have to check the return value and treat that as gospel.

If you use this method in Swift, the auto-generated Swift signature is:

func data(with string: String?) throws -> Data

Notice something?

I mean, besides the fact that Apple’s compiler/runtime magic smoothly converts between the Objective-C’s last-parameter-is-an-error-pointer pattern and Swift’s “throws” pattern.

The return type doesn’t allow for nil anymore.

You can’t check for an invalid value, if “invalid” means nil.

Instead, you can only assume that the original Objective-C implementation will “throw” an error if there is a problem.

Now, go back to your original Objective-C method. What if you return nil but don’t set the error? What does Swift do?

It does something clever.

In my testing, even when you haven’t set an error, the Swift translation layer throws an error anyway.

If you log it, it’s called nilError.

It’s got a domain of Foundation._GenericObjCError and a code of 0.

Feels a bit like a hack, doesn’t it?

But it does prevent the problem of old Objective-C code not indicating the desired result under Swift.

Translating Objective-C to Swift in Xcode 9.0 Beta 2

I’m putting together a post comparing Mac drag and drop APIs and iOS drag and drop APIs.

To prepare, I took the Xcode CocoaDragAndDrop sample project (here, last modified in 2011 with note “Updated for Xcode 4”) and converted it to Swift (here) using the second beta of Xcode 9.0.1

Since I haven’t internalized the pattern between Objective-C and Swift method conversions, I was often frustrated by how to translate Objective-C method calls to Swift method calls.

While I was working on the project, it seemed that 4 times out of 5, when I tried to go to a class or protocol’s declaration in Apple’s headers and see its Swift-ified methods, Xcode would take me to the Objective-C header instead, even though I was starting off in a Swift file.

Of course, now that I’m trying to reproduce it to file a Radar, it doesn’t happen. I wonder if that’s because the final project has no Objective-C files in it at all.

It doesn’t help that the translations changed between Swift 3 and Swift 4.

For example, NSPasteboardTypeTIFF in Swift 3 is now NSPasteboard.PasteboardType.tiff in Swift 4, with a similar pattern for all its friends.

register(forDraggedTypes newTypes: [String]) is now registerForDraggedTypes(_ newTypes: [NSPasteboard.PasteboardType]).

Etc.

It’ll be nice to be working exclusively in Swift for the rest of this effort.


1. Feedback welcome! ↩︎