Ian on the Responder Chain

Ian McCullough, Responder Chain Redux!:

Guy indicated that he feels like the decoupling offered by the responder chain is too great — that sending an arbitrary message up the chain, with only the sender for context, is insufficient to convey user intent.…

The delegate-based approach also “cuts off” the chain early, and the argument seems to be that it cuts it off at the “right” level: where context first appears. But what if there’s more than one “right” level, or more than one scope of context?

I’ve always taken it as a clue that action methods take (id)sender as parameter — which I take to mean: “Here’s an action name and a thing. Figure out what to do.”

This is probably more true on Macs, since sender might be a button, menu item, whatever, and the action method may have to do some digging to figure out intent.

But if it’s deterministic and not a guess, is that wrong? I’m not sure.

Update 10:00 pm: Guy responds on his blog:

When the table view cell was asked to perform an action it could simply pass it up the responder chain with itself as the sender. With the simple convention of an -(id)representedObject method (or Protocol if you want to be fancy) we can at least glean from the sender which item to act upon.

More Indie Numbers

Allen Ding posted revenue numbers for his app Saved.

Getting Started with Sinatra for Cocoa Programmers

Sinatra is the little brother to Ruby on Rails.

You’d think that a Cocoa guy like me — someone who’s quite happy working with a large application framework — would prefer Rails, but I find myself attracted to the smaller and lighter-weight Sinatra.

Sinatra and Node are very similar. But as awesome as Node is, it has one giant drawback: you have to write in JavaScript.

That’s also Node’s advantage. JavaScript is easy to learn and lots of people already know it. But while JavaScript, well, exists, Ruby is lovely.

Ruby has a whole lot in common with Objective-C. Both languages count Smalltalk as an ancestor: both are object-oriented and both use dynamic dispatch. I think you’d like it.

The rest of this post will get you up-and-running with Sinatra. Quickly. In like a minute.

(Yes, I know that many readers of this blog know Ruby and web services far better than I do. This is for the ones that don’t.)

Get Sinatra

In Terminal: sudo gem install sinatra

You already have Ruby, since it comes with OS X. gem is Ruby’s package manager. (Think CocoaPods, or think npm if you’re a Node developer.)

You’ll see some messages in Terminal as it downloads and installs Sinatra and its dependencies.

This tutorial will convert some Markdown text to HTML. There’s a gem for that too:

sudo gem install rdiscount

(Markdown? Discount? Got it.)

Create the Server

Create a folder on your desktop called CoolWebSite.

Inside that folder create CoolFile.markdown. Its contents should be simple:

# It Worked!
This is a cool web page served by Sinatra

Then, also inside that folder, create CoolApp.rb.

Its contents are your actual Sinatra-based server.

The top two lines are the equivalent of import statements:

require 'sinatra'
require 'rdiscount'

Then we have Sinatra’s router, where you match http methods and paths to code. This example has just one route which matches a GET request to /.

The code matching that route does the following:

  1. Read the contents of CoolFile.markdown.

  2. Turn the Markdown text into HTML.

  3. Add the HTML bits to the start and end of the HTML.

get "/" do
  file = File.open("CoolFile.markdown", 'r')
  file_text = file.read
  markdown_text = RDiscount.new​(file_text).to_html
  page_text = "<html><head><title>​It Worked!</title><body>#{markdown_text}​</body></html>"

You can see, I hope, that at this point you’re not that far from a blogging engine that reads Markdown files on disk and returns HTML.

Run the Server

In Terminal, navigate to your CoolWebSite folder. Type the following:

ruby CoolApp.rb

You’ll see that WEBrick starts up, and you’ll see a message like this:

== Sinatra/1.4.5 has taken the stage on 4567 for development with backup from WEBrick

Now, in your browser, go to http://localhost:4567. You should see the It Worked! page, in glorious HTML. (You can view the page source to confirm.)

That’s it. Now you’re a web developer — and, what’s more, you have an easy-to-learn and lightweight framework plus a language that should feel very familiar. (No square brackets, but I’m confident you can get by without them.)

Swift Literal Convertibles

Mattt Thompson, in NSHipster, brings up a potentially controverial issue.

This seems like another giant area for abuse and misuse. It worries me less than custom and overloaded operators, since it feels like something people would do less often.

And I can actually see myself potentially using the feature myself. Maybe.

But my criteria still needs to be: can somebody else read and understand my code?

Michael on Swift and Dynamic Dispatch

Michael Tsai, “It’s a Coup”:

The costs for not using message passing, on the other hand, can be high because they make the code more rigid. You cannot retroactively make compiled code more dynamic. And yet, since dynamic is not the default, the odds are that a lot more methods will be static than need to be. Most of the time, objc_msgSend is not why your code is slow, yet Swift acts like it needs to protect you from this.

I’m no fan of swizzling and don’t care what happens to it. I throw swizzling in the same bucket as SIMBL and APE and haxies, and I’m glad they’re not screwing up my apps these days. (Newer Cocoa developers have no idea what I’m talking about, I realize.)

But I do care about KVO. Very much. (Warts and all.)

This die-hard speed freak has never been concerned with the speed of objc_msgSend. I’ve noticed it in Shark and in Instruments, but the real performance issues were elsewhere in my code.

That said, it hasn’t escaped my notice that most of the time static dispatch would be fine. And most of my classes could be marked as final. So I’m not actually outraged or anything — I keep an open mind that I would actually get noticeably better performance from Swift.

Especially given that now we do have the dynamic modifier.

Objective-C is supple by default. Amazingly so. But I shouldn’t pretend I use that suppleness more than I do. And if Swift isn’t so supple — well, that’s probably closer to what we actually need than what we think we need.

Still, though, there is code in Vesper that can’t be ported to pure Swift. (Model code.) The point that you can use something like Core Data but couldn’t write it in Swift remains important. But, then, Swift is young, not even 1.0, and part of the deal is that it’s up to us developers to communicate our needs.

Server-side Config Files

Brian Schrader, Changing App Behavior Server-Side:

…it seems to me that it should be entirely possible to make iOS apps that are mostly configurable from the server-side. This got me thinking. Why not build the app to download its configuration file (i.e. plist, or Localization.strings file) remotely?

With Vesper we use DB5 for configuring things like fonts, colors, and sizes. What’s stopping us from hosting a DB5.plist on a server, and changing the app on-the-fly?

Nothing. In fact, this is how TapLynx works. (TapLynx was two-projects-ago for me; I worked on it before Glassboard.)

TapLynx is DB5’s dad. The product itself was an Xcode project and static library. You’d configure your app using a plist (they were publication-style apps, made of RSS feeds). You’d set colors, graphics, titles, feed URLs, app structure, etc. — all without writing any code.

The configuration file would ship with the app, but the file could optionally include the URL of a configuration file online which the app would download and then use. That file could be changed at will.

The configuration file could also include URLs to graphics, which the app would also download and use. (Think of graphics for tab bar items. That kind of thing.)

We haven’t done anything like that with Vesper because we don’t anticipate needing it. All it takes a server that can host static files (S3, for instance), but it’s still more moving parts, and I’d rather limit the number of things that can go wrong.

And the kinds of bugs this system can fix are limited. It doesn’t change any actual code.

Update 4:40 pm: Folks on Twitter told me about Ground Control, Mattt Thompson’s thing, which looks cool.

Guy on Responder Chain and Table View Cells

Guy English says not to wire up buttons in table view cells to first responder:

If I find a UIButton tossing some message up the responder chain, documented nowhere else except in the Interface Builder UI? That sucks. Do you think I’m being funny?

I’ve done this myself. Possibly even often. (Though it’s likely I wired it up in code rather than in IB.)

The thing is: I want the enclosing view controller to get the action message. When something needs to happen — changing the model, presenting another view controller, etc. — it’s likely that it’s something the view controller should do. Table view cells shouldn’t have that kind of power.

Guy writes:

Simply sending a message up the responder chain that some sub-item of a view has been tapped doesn’t help make the user’s intention clear except under the most superficial or specifically co-ordinated conditions.

My cases may be superficial. I expect the message only to go as far as the nearest view controller, and the only things it needs in order to know what to do are the message itself and the button that triggered it (the sender).

(If you have the button, you can find out what cell it’s in, get the index path of that cell, then look up what model object it refers to. Which sounds like a pain but actually isn’t.)

I think, though, that it’s likely I’m doing this in cases where I’m not using IB, since there’s no way to wire up the action to the view controller in code without somehow giving the table view cell a reference to the view controller, which I don’t want to do.

Is it possible in IB to wire up a button in a cell to an action method in the enclosing view controller? I would think so. (Memory is hazy on this.) If so, being explicit like that is probably a good thing, especially for the sake of the next person to look at the project.

But there’s a case that worries me: table view cells may be reused in different view controllers. In that case, I think you do want to wire up actions to first responder. (But then document them in the code, so Guy doesn’t have to go crazy.)

There’s a small case like that in Vesper: the Typography settings screen has a text preview feature, and that table view cell is the same table view cell used in the timeline.

(However, there are no buttons and no actions in this case, and so the issue of action targets doesn’t actually come up.)

* * *

Update 4:45 pm: Well, Guy’s right. The way you should do it is to create a protocol that the view controller conforms to. The cell’s delegate is the view controller.

(This way the cell doesn’t need to know about a specific class of view controller: it just needs to know about that protocol. I have real-life cases where a specific UITableViewCell subclass is used by different classes of view controllers.)

The button should be wired to an action method in the cell. That action method should call the right method on the cell’s delegate.

It’s likely, in this scenario, that you also want the cell to have a reference to a model object. I myself would make this opaque — the cell could have an id representedObject property, which is set when the view controller configures the cell.

This way, inside an action method in the cell, to actually do the thing, you’d have code like this:

[self.delegate doAThingWithAModelObject:​self.​representedObject];

[Sponsor] Presence: access your Mac’s files from anywhere

Presence gives you secure internet access to all your Mac’s files, from iPhone, iPad, Mac, or PC. That’s all your files — anytime, anywhere.

And you can share files and folders with others too. Send large files or provide access to a folder, all with the greatest of ease — just right-click, choose your options, and send a link.

You can even look through your Mac’s camera from anywhere in the world.

All this, and it’s private — your files live on your Mac, not on some company’s server.

Presence is free to download and has a two-week, fully-functional free trial. See the Presence web site for full details of an app that's worth getting to know.

Gus on Apple and Seattle

Gus Mueller suggests that Apple should open a Seattle office:

So when Apple says “Hey, we’ve got a job down in Cupertino,” the usual response is “Uh, that’s great. I’m going to stay here thank you very much.”

I wouldn’t be surprised if the Seattle area is home to the largest Cocoa developer community outside California. And we already do have remote Apple employees here.

It’s a beautiful city and a beautiful region. And it’s progressive — we have marriage equality, legalized marijuana, and a $15 dollar minimum wage (well, coming soon).

Me, I’ve already got a thing. But if I didn’t, and I were looking for a job, and Apple had a local office, I’d strongly consider it. But I wouldn’t consider leaving Seattle.

Shiny Snippets

Nick O’Neill’s that thing in swift shows how to do things in Swift you know how to do in Objective-C. (Via the very awesome iOS Dev Weekly, which you should subscribe to.)

Mark on Design

Mark Kawano, writing for Inc.com, The Biggest Lesson I Learned as an Apple Designer:

Waiting to launch a product until its “magical” moment goes against the concept of MVP, or minimum viable product, which has become so trendy in business over the last few years…

…entrepreneurs need to be very careful in their interpretation of what a minimum viable product actually is. If you’re launching something in a space where there are a lot of people trying to do something similar to you — for example, with a consumer product — then the bar for MVP should be ridiculously high.

objc.io on Testing

As always, the latest issue of objc.io should be read from cover to cover.

An Appreciation of The Leftovers

Informal polling tells me that most people don’t love The Leftovers.

I don’t love it either — but I like it and I watch it.

It has no likeable characters and you don’t care what happens to them. You don’t understand a bunch of it: a bunch of things are unexplained.

It’s creepy — sometimes massively creepy — but not in a fun way: there’s no thrill-of-the-creepy. It’s sad, tedious, and ugly.

There are no redemptive moments or moments of hope. Things start out as unspeakably awful — and go south from there.

And just when you think somebody is getting somewhere, just when you think there might be a break, the darkness snaps shut tight.

It reminds me in a way of The Metamorphosis. It starts out bad — the protagonist has been turned into a giant bug — and then he suffers, and then he dies. He’s not likeable (you suspect he deserved this fate) and his family is even worse.

And there’s no explanation for why he turned into a monstrous vermin.

And there’s no explanation for why I love The Metamorphosis so much.

It’s not like other stories that are so awful. The British version of The Office was kind of like that — so sad, so yucky — but then you find to your surprise that you care about the characters, and the big and small good things that eventually happen shine even brighter for the contrast against the bad things.

The Leftovers is not like that.

It makes me think of an America that’s one terrible step away.

After September 11, after years of war with no end, after the horror of the lack of horror over our beloved nation torturing people, after the militarization of the police and the rise of the prison and surveillance state, after the worst economic shock since the Great Depression, after the realization that climate change is devastating cities now and our can-do country can’t summon the political will to save itself — it feels as if The Leftovers is just one trauma away from where we are right now.

As fiction I love it, because I love the courage of stories like The Metamorphosis — and, well, there’s probably something wrong with me.

As social commentary it’s an angry warning, and worth paying attention to, before we end up living in it.

Chris on Implicit Optional Chaining

Chris Lattner responds to David Owens on implicit optional chaining on the Apple Dev Forums. (Login required.)

The gist: the ? lets you know that subsequent sub-expressions may not be evaluated.

Josh on Vesper

Josh Ginter reviews Vesper. It’s about typography and how it fits into his analog workflow. I love this review.

National Moment of Silence - Seattle

It’s not a protest or occasion for speeches — it’s silence. Two locations: 4th and Pine downtown and the Queen Anne Baptist Church. Details are here.

Kyle on Presentation Controllers

Kyle Sluder, UIPresentationController is (currently) a deficient API:

Note that this implies that the popover presentation controller does not exist until after the call to -presentViewController:…. As such, the popover can’t be configured until it’s already been presented!