Hacktober 2017 Log #2 – Better UICollectionViewCells

Hacktober continues! Hacktober is an event hosted by Github and DigitalOcean to promote contributing to open source. And for this year, I decided on a theme; improving accessibility. And to keep track of what I learned, I’ll be maintaining a log here.

For my second log, I’ll continue working on the CocoaHeadsNL app. It’s very possible I’ll complete Hacktober just on that app, but… why not?

Better UICollectionViewCells

There are a couple of place in the app where the cells could use some more VoiceOver functionality. For example, in the Jobs screen, VoiceOver only reads the job title in each cell. There is only so much time you can hear “iOS developer” before the jobs start blurring together. Also, the job title label is the only part that can be tapped by a VoiceOver user, which makes it hard for them to search this screen.

Screenshot of Jobs screen, where the tiny job title is the only thing that can be tapped and read.

Instead, let’s see if we can VoiceOver mention the company (e.g. “Programming Hero at Noodlewerk Apps”) and make the entire cell tappable.

Make the entire cell tappable

First off, let’s check the cell structure. As you can see in the image below, the views that make up the cell are direct children of the jobsCell.

Screenshot of jobs cell hierarchy, with all UI elements as direct children of the cell.

However, it’s somewhat difficult to make jobsCell accessible in Interface Builder (the options just don’t exist). So instead, we’ll put everything in a container view and make sure it is the only view with accessibilityEnabled set on true. And for good measure, we give it the accessibility traits Static Text, Button and User Interaction Enabled by selecting those options in Interface Builder.

Screenshot of jobs cell hierarchy, now with all UI elements contained in a container view.

Now, instead of only the label being tappable, the entire cell can be tapped. And swiping left or right, selects the other cells as usual.

Improve the accessibilityLabel and add an accessibilityHint

Improving the accessibility label is trivial now. And because it’s useful to know what happens when you double-tap a selected cell, we add an accessibility hint as well;

var job: Job {
    didSet {
        imageView.image = job.logoImage
        textLabel.text = job.title

        let text = NSLocalizedString("%1$@ at %2$@")
        let accessibilityLabel = String(format: text, job.title, job.company.name)
        container.accessibilityLabel = accessibilityLabel
        container.accessibilityHint = NSLocalizedString("Double-tap for more details.")

Now the cell speaks;

Programming Hero at Noodlewerk Apps. Button.
<longer pause>
Double-tap for more details.

That was easy. Great success, once again!

Sidequest; where’s our data?

The above wasn’t actually all that simple. What I figured out was that the Job object didn’t even have a company reference, or even a reference to the companyName. Just an image for the company logo. Working on accessibility is a great way to find bits in your code that – for lack of a better phrase – don’t make sense. So while you’re making your app more accessible, you’re also improving your app architecture as a whole!

Wrapping up

You can check out the pull request here. And merged too! I also had to add a small improvement to the job harvester script.

Lessons learned:

  • Use a larger container view to encapsulate all of a UICollectionViewCell’s accessibility elements.
  • When localizing, use the %1$@ notation instead of just %@ for formatted strings. It will make your life easier when you start adding more diverse languages.
  • Working on accessibility makes your entire app better!

If you have a comment or a suggestion, send me a tweet or a toot!