inessential by Brent Simmons

July 2014

How to Be Wrong on the Internet

Sometimes I hear from people who’d like to blog more — or at all — but they worry, they say, about “being wrong on the internet.”

Me, I do it all the time. I’m constantly wrong on the internet. Here’s how I think about it:

Blogging is, for me, part of the process of getting to the truth.

Everything is provisional — it’s what I think now, and I might change my mind in a year. Or in a day. Or in a minute, when somebody posts (or tweets) more or better information or has a solid argument.

And that’s the part I love. A recent example: while writing the Vesper sync diary I got a ton of great feedback that changed my mind on some things, and that feedback ended up making those articles better and it made the app better.

The fun part is documentating all this. It’s learning-out-loud.

But to do that means thinking a little bit differently than you may be used to. Instead of taking feedback as criticism or correction, take it to mean that the process is working. If you learn something or change your thinking, then that’s great. That’s the point.

The feedback may also not change your thinking, but you may understand your thinking better and end up being better at defending and articulating it. That’s great too.

This may take some courage at first. But soon you’ll find that it doesn’t hurt at all.

Me, I’d be happy if everything I post is wrong. Because then I get to learn.

Ben on Building Businesses

Ben Thompson:

What stands out to me about Love’s approach was that from day one his differentiation was not based on design, ease-of-use, or some other attribute we usually glorify in developers. Rather, he focused on decidedly less sexy things like licensing. Sure, licensing is particularly pertinent to a dictionary app, but the broader point is that Love’s sustainable differentiation was not about his own code. Sustainable differentiation never is.

Mark on Prosperity Gospel Business Reporting

Mark Bernstein:

Prosperity Gospel business reporting holds that, when a product succeeds, it succeeds because the CEO or the product manager is brilliant and wonderful, a romantic hero like Steve Jobs. When a product fails, its failure stems from the shortsightedness and shortcomings of the foolish and ill-behaved management. Just like Steve Jobs, back in the day, was the dirty hippy who nearly ruined Apple.

Why I Love Indies and You Do Too

As much as I love Macworld, I have to say that the one indispensable website in our community is Daring Fireball — an indie website.

As cool as Twitter is, its early success in our community was due entirely to Twitterrific. And it took The Iconfactory to come up with the word “tweet” and the bird logo for Twitter.

It took Loren Brichter to invent pull-to-refresh in Tweetie.

It took Marco Arment to invent the entire read-later category with Instapaper.

And me, I shipped the first Cocoa RSS reader at a time when Mac users mostly hadn’t heard of RSS. (And while corporations have dabbled with RSS, it’s pretty much back to its roots now as an indie technology.)

* * *

I can’t find it now, but I was asked on Twitter a couple days ago why I placed such emphasis on indies. Isn’t the point that we want high-quality software, and it doesn’t matter if it comes from indies or corporations?

I’ve noticed something obvious about popular music — it’s almost never instrumental. There’s always a human voice singing a melody. We humans love human voices.

That’s what we get from indies that we don’t get from corporations. We get that human voice and the emotional connection that goes with it.

* * *

But it’s not just that human voice, and the thrill it gives us to see a smart person or team doing great work. It’s also that indies make software that no corporation would ever make.

Think of MarsEdit, a desktop blog editor that works with a variety of blog systems. While WordPress writes an app that works with WordPress, it takes an indie to write the app to connect to everything.

Or think of Pixelmator and (my favorite) Acorn. What corporation would go up against Photoshop? It takes indies.

A great example is Capo. I can’t imagine a corporation building this — and, if they did (with a team of six, probably), they wouldn’t be one-tenth as hardcore as one Chris Liscio.

Inventiveness, passion, and courage comes from indies, not from people who watch the bottom line.

* * *

But indies do have to watch the bottom line — at least enough to be able to survive as an indie so they can keep making software.

And I think we’re already missing out on great software that would have existed in a better context.

So it’s worth thinking about a few things. One is how things could be better for indies — Marco, for instance, suggests that the App Store should get rid of the top lists.

Another is that you, as an indie or potential indie, should know what you’re signing up for, and you should have enough information to make smart decisions that will allow you to keep doing what you love.

The advice I’ve seen boils down to a few things:

  • Start with small apps. Do a few of them.

  • Strongly consider doing Mac apps too. (You can charge sustainable prices for Mac apps.)

  • Start your business as a side business until it’s making enough money to support you.

  • Do contracting as needed to make up the income gap.

  • Don’t skimp on marketing. It’s important.

  • Persevere.

But know that you’re still going to fail, most likely.

I would love for you to prove me wrong. Write something that blows my mind and that makes you successful.

Ignore the doom and gloom. Make me eat my words. Please!

Jake on CloudKit and Groups

Jake Savin: Square Pegs and Round Holes:

It’s possible separately via a web portal (not programmatically as far as I know), to configure a subset of data to be editable only by specific people, but the idea is more about providing a way for the maintainers of some data resources to update that data, than it is about providing a mechanism for users to create ad-hoc groups among themselves. (i.e. dynamic configuration data that’s loaded by the app at launch.)

While this is a super useful feature, the value of which hasn’t really been called out much by the iOS dev community, it is not what Marco Tabini described. (I can see how the misunderstanding arose though.)

Mark on Mobile Software

Mark Bernstein: The Mobile Software Disaster:

It’s clear that mobile apps have the ability to make people smile, to make people think, to make people get more stuff done., to let people do things they couldn’t do without them. Making software is productive: it creates value for lots of people. We need to be able to capture some of that value, or people will stop making software.

Nick B on Leaving Indie Life

Nick Bradbury:

In what feels like a different life now, I used to be a fairly well-known indie developer. I spoke at events like SXSW, and my blog had a large audience of people who liked hearing about my work on HomeSite, TopStyle and FeedDemon.

Nick was the single greatest indie Windows developer. So good that I once called him an honorary Mac developer. (Well, I was being complimentary and a jerk at the same time.)

I should point out that I ripped off some of his ideas from FeedDemon entirely without shame — and with Nick cheering me on.

A lot of mobile developers have left the indie ship and done as I have and joined a larger company, many of which look at mobile apps as a free (or nearly free) complement to their other offerings. There’s plenty of opportunity here for mobile developers, and I think that opportunity will continue to grow for a while.

He’s right. (Nick works at Automattic, by the way, which is a great company.)

Nevertheless, I still believe with all my heart (more than my brains) that there’s plenty of room for indie mobile developers. It’s just that the most straightforward path — write one great app and get rewarded — isn’t necessarily the smartest.

On Pricing More

Robert McGinley Myers suggests raising prices:

But when I look at that sales chart for Unread, and see that huge spike in the first few days, I see myself and other people like me, people who love these beautifully designed, “hand-crafted” apps.

We aren’t buying these apps on impulse. We’re buying them because we read the reviews and we know what the best apps are, and we want to own the best. Maybe indie devs need to stop chasing the normals (who think everything should be free anyway) and just charge a fair price from the folks who care.

I think what would happen is that launch week would be even better — but every week after that would be much worse, in terms of both units and revenue.

Would you have bought Unread at $19.99? Or even $14.99 or $9.99? I don’t know if I would have.

Faruk on Indies

The iOS Indie That Could:

First, let’s look at the skills involved in creating and publishing a great app like Unread. You need a good understanding of interaction design, UI design, (most likely also) icon design, and having great taste and the ability to know when to say “No” to things are a boon to its positive reception by critics and users alike. Then, you need to do the programming of the application, which generally requires at least a decent understanding of database architectures, MVC principles, the main programming language and its frameworks, and generally good programming discipline. Next, you need content strategy skills: all the labels and text in your UI send messages to the user, and if they’re poorly written or unintuitive, this will cost you in significant, but difficult to measure, ways. The same applies to the marketing of your app: the website promoting it, the language used in your AppStore listing, the quotes you provide in interviews, and so on. Good selling skills overlap with this, but if you’re simply publishing it on the AppStore and not making direct sales to, say, enterprises or businesses, you probably don’t need the equivalent of a sales agent. Then, from your business end, you need all the various business management skills as well as the project management chops to keep yourself on track, issue yourself realistic deadlines, and so forth.

Organization

Marco, in App Rot:

Apple’s App Store design is a big part of the problem. The dominance and prominence of “top lists” stratifies the top 0.02% so far above everyone else that the entire ecosystem is encouraged to design for a theoretical top-list placement that, by definition, won’t happen to 99.98% of them…

The best thing Apple could do to increase the quality of apps is remove every top list from the App Store.

We’re not employees, so a union doesn’t make sense. But it’s still true that a group of some kind has more leverage than individual developers.

What I’d love to see is something formal where Apple listens to developer feedback about the App Store. It’s their App Store, but it’s also the only market place for iOS apps — and, because it’s the only game in town, fairness suggests that we’d have at least an advisory role (beyond kvetching on blogs and Twitter and Radar).

But how this should work is beyond me. (I grew up more on Robert Heinlein than on Ursula K. LeGuin.)

Shopster 2013

More numbers. About a year ago Pablo Bendersky wrote about his app Shopster:

I can’t say the first day sales were a disappointment, as I was not sure what to expect, since our previous apps did not have the coverage Shopster had. We were surprised to see the app had only sold about 200 units…

As you can see, in our first week averaging 100 sales a day, our app ranked consistently in the top 100 productivity apps…

Shopster got reviewed by Gizmodo and finally, on April 11th, it was picked by Apple as New and Noteworthy. At the point we thought sales would skyrocket…

As you can see, things did not get better, and our app averaged 41 sales per day.

Say the app was priced at $1.99. If it had sustained the opening rate of 100 sales per day, this means $199 per day, which is $139.30 after Apple’s cut.

Say it’s just one developer. That developer would make $50,844.50 in one year, at that rate.

If that one developer writes two or three apps that do as well, then that’s a pretty good living, for sure.

But the average was 41 per day, which means $81.59 per day, which is $57.11 after Apple’s cut. That turns into $20,845.15 per year.

Now you need to write five of these to have a good year. (More if it’s a team rather than a solo developer.) And you have to support those apps, and probably do another five next year because the bulk of sales happen at launch.

My city (Seattle) is in the process of raising its minimum wage to $15 an hour, which is about $30,000 for a full-time job. Many iOS indies would do better at minimum wage jobs here than on the App Store.

iOS Indie Game Numbers

Chad Etzel:

Even though I managed to bring in a paltry $498 for a year’s worth of side-project time, it gets even worse. I paid nearly $700 in Facebook and Twitter mobile ads to try and market them. I also bought an iPad Mini and an iPod Touch for development and testing, so I’m even deeper in the hole overall.

I was wondering if games were different than other types of apps — easier to make a profit, maybe? Or harder?

This is just one developer’s experience, but if it’s at all representative then games are probably harder.

Tyler on Mac Apps

Tyler Hall:

In 2007, I priced the app at $7. Over time I raised the price to $9, $12, $14, $19, $24, $29, $34, $39, and, now, $49. With each price increase my total sales and revenue have only gone up. And, as an extra bonus, the quality of my customers has increased as well. I never received as many angry emails from customers as I did when the app was priced cheaply.

(Via Jared Sinclair.)

Lots of Apps

Benjamin Mayo comments on Jared Sinclair writing about Unread’s revenue:

In my opinion, you make money on the App Store by selling small things — its very nature is a bitesize marketplace. This is how you maximise your effective hourly wage. This doesn’t mean you have to turn around crap. You can still output quality pieces of software.

I think he’s right that this is a workable strategy.

The obvious downside, though, is that you don’t get apps like Overcast, Unread, Tweetbot, and my own app Vesper (and plenty of others) if everyone sticks to this strategy.

We want those kinds of apps, not just the bite-sized apps.

More on iOS Indies

When I asked who all the iOS indies are, I got a bunch of good responses. By iOS indies, I meant:

• People making all (or almost all) of their money from iOS.

• And who are making that money from publishing their own apps, not via contracting or a paycheck.

There are plenty of people with both iOS and Mac apps, and plenty of indies who make much of their money from contracting. But I was curious about the pure iOS indies, since I thought it would tell me something about the ability of indies to make money on the iOS App Store.

(Games, by the way, are another country. I should be explicit about not thinking about games, since I don’t know anything about the market or what it takes to make an iOS game. It’s possible that game-writing is a wonderland of fun and money. I don’t know.)

There aren’t many pure iOS indies. I’m sure I’m missing some, but the names that kept coming up were David Barnard (Launch Center Pro), Jared Sinclair (Unread), David Smith (Feed Wrangler and others), Charles Perry (Action Lists and Benjamin), and Greg Pierce (Drafts and others).

(Congratulations to these folks! And to the others whose names I missed. You’re living the dream, and that’s cool.)

I think my point still stands — pure iOS indies are fairly rare. I can easily come up with a bigger list of pure Mac indies, even though iOS developers in general outnumber Mac developers.

If you want to write your own iOS apps, it appears that either you accept the likelihood of a pretty low income or you have a day job, write Mac apps, or do contracting (or some combination).

I think this is too bad. It seems like the iOS market is so huge that it should be able to support lots of iOS-only indies.

But with how prices have fallen — how people are now accustomed to not paying anything until they’re hopelessly addicted and need the $4.99 packet of imaginary things that will get them to the next level — I can’t recommend to anybody that they quit their job to just write their own iOS apps.

(Unless those apps are games. Maybe games are fine. I have no idea.)

There’s a downside to this beyond just the vague feeling that it’s a shame that iOS developers have to supplement their incomes — it’s that any rational developer aware of the economics will not be able to make as big an investment in iOS apps as they would if they could expect their effort would be rewarded.

Consumers win in terms of quantity of choices and low prices, but not in terms of quality.

[Sponsor] Creating static blogs made easy!

Statiked is a blog client for your static blog hosted on Github and S3.

The online world has seen a new revolution lately: static blogs. However, as the current tools that are available to host and manage a static blog stand, it is only accessible to a minority of bloggers out there. Even seasoned programmers who use Github daily often find it difficult to write and publish a blog post. Statiked takes out all the pain points in publishing to a static blog.

Statiked allows you to compose your article in your favorite text editor. Currently it supports, TextMate, TextEdit, Sublime Text 2, and BBEdit. You write all your articles in plain text using Markdown. Statiked generates the corresponding HTML before publishing it to the host.

If you are like us and don’t want to leave the comforts of a blog editor which you are used to, Statiked provides an XML-RPC server built in. Point your favorite blog editor to the URL provided by Statiked, and blog as if you are publishing to any hosted blog.

There are three beautifully designed responsive themes packaged within Statiked. With a bit of hacking you can port your Jekyll or Wordpress theme to use with Statiked too. Porting a theme is easy as Statiked supports the famous Liquid template system.

Statiked is a useful tool for any blogger who wishes to host a static blog. There are no bash commands to remember. No scripts to deal with. You do everything through a simple and intuitive UI. Publishing to a static blog is as easy as writing an email. Use your time to focus on writing. Write Just Right!

You can get Statiked from our website. Follow us on Twitter at @statikedapp.

I Was Wrong — You Totally Can Use CloudKit for Identity

See Session 208, Introducing CloudKit.

Your app gets a stable but random user identifier that does not include any user information. Two different applications get different identifiers, but the same application run by the same user on different devices get the same identifier, as you’d expect.

From the session, at 40:36:

And lastly, this is an independent API. This is a section of the CloudKit framework. You can use this in collaboration with the database API, or you can use this completely separately. We’ve given you enough support that, if you wanted to, you could implement a login-via-iCloud flow in your application using the CloudKit framework.

Unread’s Numbers

Jared Sinclair writes about Unread sales.

(I bought Unread about a month ago, by the way. It’s a very good app, and I recommend it.)

Contrast Jared’s numbers with NetNewsWire’s numbers in 2004 and 2005 (the last time I paid attention to its sales) — NetNewsWire made 5 figures every month, month after month.

This was before the App Store. It was a Mac app in a small market. (Far smaller than iOS, and much smaller than the Mac market is now.)

Setting Expectations About CloudKit

Macworld: Why you should care about CloudKit:

The big difference is that the information stored in it can be made available to multiple users, allowing them to collaborate and share information through the cloud—something that iCloud “Classic” was unable to do…

Don’t let the term “public” put you off, though—CloudKit doesn’t force all the shared data in a big bucket that is automatically visible to everyone who installs a particular app. Instead, developers will be able to protect the information as they see fit, allowing, for example, users from a particular group or organization only to have access to specific content…

It’s not hard to see that CloudKit greatly simplifies the creation of apps that revolve around multi-user collaboration. Previously, creating a group chat app like Glassboard, or a team-based task management software like Wunderlist, would have required a significant amount of work.

I don’t see how this is true. While it’s technically possible to use the public data for group collaboration, it’s only the code in the client app that enforces this. CloudKit has no notion of groups.

It would be irresponsible to use the public data for private group collaboration.

Neither of the two apps mentioned as example — Glassboard and Wunderlist — should use CloudKit.

And, since CloudKit is iOS and Mac only, and those two apps exist on other platforms, they couldn’t use CloudKit even if it did have private group data.

CloudKit is cool, and I think lots of developers and users will benefit from it. But it’s important to set expectations properly, and not suggest that it’s useful in cases where it’s not.

(Hopefully that will change. I’d love for CloudKit to understand groups.)

Also, there’s this:

Finally, CloudKit allows third-pa>rty apps to piggyback their authentication mechanism on Apple ID, thus making it easy to tell each user apart in a unique way without having to write and maintain a login system—and without forcing users to remember yet another password.

I don’t see how that’s true, either. If CloudKit gives you a user-specific token that identifies a user, sending that token to your own server — without an additional authentication system — isn’t secure. An attacker could submit random tokens until they found somebody’s data.

Update a few minutes later:

Kyle Sluder asks on Twitter:

If authentication is user id + nonce, how is it not secure?

Good question. Perhaps this could be made to be secure.

So I’ll make another point: in the absence of Apple saying, “Yes, you can use it this way,” I wouldn’t. It feels like a misuse of the system, and something Apple would recommend against. Putting your app in that position is not a good idea, especially given that it’s the kind of practice Apple could choose to disallow.

If I’m wrong — if Apple is indeed offering just the authentication part of CloudKit as a service to developers — then I’d like to see where this is spelled-out.

Update 9:45 am:

Well, Tom Harrington tells me that Apple has indeed said you can use CloudKit authentication as a service.

It was specifically mentioned in one of the CloudKit WWDC sessions. Log in with iCloud instead of Facebook or whatever.

That’s really cool. I’ll go back to the session and double-check, of course, but I don’t doubt Tom. (He knows this stuff.)

Update 10:06 am:

See I Was Wrong — You Totally Can Use CloudKit for Identity.

Who at the Table is an Indie iOS Developer?

Until last night’s unofficial Xcoders I hadn’t thought to ask this question.

There are a ton of Mac and iOS developers in the Seattle area — and almost all the iOS developers are making money either via a paycheck (they have a job) or through contracting.

The only local indie iOS-only developer I could think of was me — and even that won’t be true for much longer, as we’re working on Vesper for Mac.

There probably are other local indie iOS-only developers, but I just can’t think of them at the moment. At any rate, they’re rare.

To be fair, there aren’t that many more indie Mac developers. There’s Gus with Acorn. John Chaffee and BusyCal. Chris and Napkin. Hal Mueller and SkunkTracker. The Vellum folks. But that’s a bigger list than indie iOS developers.

(Noted: not all of the Mac developers are making a living solely through their Mac apps. Gus and John are, but Chris, for instance, also does iOS contracting.)

I think I have two points.

One is that indie developers — people who make all or most of their money via products they create and sell — are fairly rare these days. Most of the local developers I know work at Omni, Black Pixel, or Apple or do contracting.

The second is that indie iOS developers are more rare than indie Mac developers. Though iOS developers outnumber Mac developers by a huge margin, they’re under-represented in the indie community.

This isn’t scientific or anything. I’m just observing the local community, and I could be missing important data.

But if I’m right that this is the general trend, then it means that people making a living as indie iOS developers just isn’t a thing these days. Some money for iOS development is coming from companies like Omni that do create products — but most of it appears to be coming from corporations that need apps (or think they do). Places like Starbucks and Target.

The dream of making a living as an indie iOS developer isn’t dead — see Overcast as a recent example — but, if I’m right, hardly anyone believes in it any more.

I’d love to be wrong.

Who are the indie iOS developers? Who, that is, is making iOS apps only and supporting themselves solely or largely via sales of their apps? (Anywhere, not just in Seattle.)

You could say Q Branch, but we’re working on a Mac app. Marco has a new app, so that’s one. You might say Loren Brichter, but it’s possible his money comes more from Facebook than Letterpress. (I just don’t know.) You might say Michael Simmons and Flexibits, but they have a Mac app.

Found another one: Tutu Lab. That makes two. Who else?

Prefixes Considered Passé

Me on Twitter:

Decided. No longer prefixing classes in app code, even with Objective-C. I can hear your screams and I don’t care.

Prefixing was always a poor solution to the lack of namespaces in Objective-C. There was no enforcement anywhere — and a prefix like RS could stand for Ranchero Software, Red Shed, Red Sweater, and Rogue Sheep. (Those are all real companies that used RS.)

A couple things have made me decide not to use prefixes in app code class names anymore.

First is that I’m spoiled by Swift. I didn’t think it would make much difference to me to be able to use naked class names — CreditsViewController instead of VSCreditsViewController, for example — but it does. It’s much nicer.

The second is that the Xcode 6 betas no longer ask for a prefix when starting a new project. And it creates AppDelegate and friends — not BSAppDelegate and friends.

If I had to guess, I’d say that Apple engineers are also spoiled by Swift’s no-prefixing, and somewhere in developer tools a decision was made not to push prefixes for app code any more.

This — no prefixes for app code classes — will become a recommendation, I’d bet.

There is a caveat, though. There could be non-prefixed class names in Apple’s frameworks. I haven’t personally verified these, but Spencer MacDonald says there’s a Message class and Saul Mora says there’s a BluetoothDevice class. There could be more.

Avoiding these conflicts is the point of prefixing. We can argue that it’s the responsibility of frameworks to use prefixes so that we app developers don’t have to watch out for these — but arguing doesn’t make it so.

Nevertheless, I’d bet these are rare enough that it’s the worth the potential hassle, and we can always file Radars if these come up.

Better Words

James Somers (via Gabe Weatherhead, via Michael Tsai) writes about using a better dictionary — and how to get it installed on your Mac, in Dictionary.app.

Had double-rainbow guy been raised on this older Webster’s, he might have read this:

Besides the ordinary bow, called also primary rainbow, which is formed by two refractions and one reflection, there is also another often seen exterior to it, called the secondary rainbow, concentric with the first, and separated from it by a small interval. It is formed by two refractions and two reflections, is much fainter than the primary bow, and has its colors arranged in the reverse order from those of the latter.

I had never noticed that the second rainbow has its colors in reverse order. This is the quality of eyesight that we want in a dictionary.

I looked up “glass,” and noticed that the default dictionary and this old Webster’s both note that it can be used as a synonym for “to reflect.”

The default dictionary provides this example: “the opposite slopes glassed themselves in the deep dark water.” Which isn’t terrible, but it sticks to the literal pretty closely — while the old Webster’s give us two examples, one literal and one not, to illustrate the range of uses.

Happy to glass themselves in such a mirror. —Motley.

Where the Almighty’s form glasses itself in tempests. —Byron.

(Byron. Wow. I like a metaphor like that because you learn something about both sides, about the Almighty and tempests both.)

This is after two minutes of clicking around. There’s an entire language of rewards in there.

(Tip: the original article suggested p { line-height: 0.7em } — which I think might be a typo. I went with 1.2em.)

Swift and Internal Access as Default

So if internal access is the default, and I don’t want to use it (or want to use it exceedingly sparingly), what do I do?

I can think of a few options.

  • Just pay attention. By convention treat internal as private, and pretend that other objects can only see what’s public. The compiler won’t enforce this, but it’s the kind of convention that’s easily enforced manually if it’s habit.

  • Actually mark every damn thing as either public or private. Just don’t ever use the default. That’s a pain, but also the kind of thing that’s not that hard if it’s habit.

  • Modularize.

The last one intrigues me. My app could be broken up into modules — Q Branch Standard Kit, DB5, data layer, syncing, images/attachments rendering and storage, and user interface.

In that case, I’d be less bugged about objects presenting a larger API, since the objects that could see that expanded API are only other objects in the same module.

I do have a natural bent toward modularizing. I’ve always liked splitting things into frameworks. And the tea leaves clearly spell out Way of the Future for this approach.

But I have two objections, one practical and one theoretical.

The practical one is that I’m still shipping an app for iOS 7, which doesn’t support embedded frameworks. (Or, not exactly.) That problem will take care of itself after a while — but still, it means that right now I’d have to start an iOS 8 branch just for frameworks, which leads down the road to merge debt. Merge debt’s a killer.

The theoretical one is the same problem I expressed previously: where I used to think about public vs. private, now I have to think about public vs. internal vs. private, and I’m not sure that that additional complexity is good for me. The discipline of public vs. private, along with the drive to reduce what’s-public down to the barest minimum, has been good for my designs. It suits my brain — which is more experienced than it is clever — quite well.

There’s an argument that frameworks really need this, that objects need to expose some bits to their neighboring objects that they don’t expose to the world. I bet that that’s how many frameworks have been written. But I also bet that that’s not how I’d do it.

But I could be wrong, and I could be missing out, and maybe I’m just being a stick in the mud.

Swift Access Control

It’s out, and we have public, internal, and private levels of control.

Public means the world can see it; internal is visible inside a target; private is inside-the-file only. (I think I have this right.)

My first thought: I’m not sure I’ll ever use internal.

My second thought: protected would have been nice. I actually used this in Objective-C, back in the days when we’d declare our instance variables.

My third thought: maybe I don’t really care about protected.

I’ll clarify.

With my Objective-C header files I’m accustomed to thinking about only two levels of access: public and private.

I used to use @protected sometimes, back in the days when we declared our instance variables. But I haven’t missed it. And I haven’t even once wished for a target-only access level.

Public-or-private as the only choice imposes a discipline that makes for simpler code. I design for the least-possible surface area, and this makes me think harder about design. If I use internal (or protected) access, then my designs are more complex, and I’m one step away from taking expedient shortcuts at the expense of good design.

So I have classified internal as a code smell and decided not to use it. But this is entirely provisional, because this stuff is all so new, and because I haven’t thought about it as much as the language designers have. I’m a total Swift newbie, like almost everybody else. (I may end up a fan of internal access, in other words, however unlikely that seems right now.)

Glassboard Changes

I’ve been watching with interest as Justin Williams works to turn Glassboard into a sustainable service. It’s not profitable or even break-even at this point — but he’s making changes to turn this around.

Those changes do mean that people using Glassboard for free will be more limited than they were. For example, boards created by non-paying users will be limited to five members — but people can buy a basic membership for $1/month and get up to 25 members.

That’s reasonable. If something isn’t worth $1/month to me, then it’s not worth my time at all.

A few people are complaining on Twitter, of course. And some of the complaints seem to be based on the same magical internet thinking that has led to so much doom and heartbreak — that if you make a whole bunch of people happy by giving them wonderful free things, you’ll be rolling in dough.

And when that thinking is contradicted by facts and logic, that magical thinking says: you should have given them more and even better wonderful free things, and it would have worked out.

I like how Justin is handling all this. He’s direct and clear. Some may take this as bluntness, and it’s true that Justin might never get accepted to the diplomatic corps. But it’s because he doesn’t care about being liked so much as providing a great service. And that’s what we should want him to care about.

I use Glassboard all day every day. Our internal Q Branch communication goes through Glassboard. We have a board for Vesper beta testers. Chris Parrish and I have a board where we work on The Record. Seattle Xcoders has a board. My family has several boards.

I like that it’s simple and private, that there are no ads, and that we’re not being tracked for nefarious reasons. It’s no Google or Facebook where the users are the product — it’s an honest service that is itself the product. As it should be.

I can imagine being in Justin’s shoes. As a fellow indie doing a hard job, he deserves our best wishes. And, if you find the service useful — as I most certainly do — it deserves your financial support. Because we developers all know that wonderful things are not free — or, if they are, they don’t last.

[Sponsor] UI for iOS: Filling Gaps in the UIKit Framework

Telerik UI for iOS is a native development toolset featuring an advanced Charting library with 10+ fully customizable chart types, Calendar, AppFeedback and Data Sync controls.

Integrating the components in your Xcode project is very straightforward thanks to the easy-to-use API. The product comes with dedicated support and detailed documentation of the API.

Give it a try for free and get advantage of the dedicated support that comes even with the trial version of the product.

Vesper, Auto Layout, and Justin’s Book

Last night I decided to use auto layout for some sub-sub-sub-view in Vesper for iPhone. Worked great. (I’m getting the hang of it.)

Except that it broke the interactive pan-back-from-detail transition. The view just wouldn’t move with your finger.

I have no idea why. I pulled out the little bit of auto layout code I was using.

So: enter Justin Williams. Today I emailed him to ask if his new book covered auto layout and interactive transitions, and he said he’d give it a shot.

I like how he’s doing this. He’s put out an early, unfinished version of his book and he’s getting feedback as he goes. Very cool.

The thing I need to learn isn’t really using auto layout for layout — I’m getting the hang of that part. The Mac version is all auto layout, even. But the iPhone app barely uses it all, since the app is so full of animations and interactive transitions, and I just don’t get (yet) how to use auto layout with all this.

You might think I’d feel some urgency about auto layout, given the rumors of 4.7” and 5.5” iPhones. If the rumors are true, those screens might have different point dimensions than what we’ve seen so far. (Maybe. Even if they don’t, we should be prepared for it.)

However, it’s no harder to support different dimensions using layoutSubviews and layout code than it ever has been. There are a few places where Vesper hard-codes screen width at 320 points — but I could fix those in 15 minutes. The Credits screen is written to expect just two specific heights, but it wouldn’t take much work to make it work with variable heights (and it would probably simplify that particular code, actually). No other part of the app expects any particular screen height.

It’s not urgent, in other words, but it’s still important to switch to auto layout.

What’s cool about auto layout isn’t that it allows us to deal with different screens — we can do that the old-fashioned way just fine. All those Mac apps for all those years handled resizing windows and views without auto layout, after all.

What is cool is that we can switch from imperative to declarative style, and that matters. The more we can do of that with our UI code (which is so fiendishly boring to work on) the better.

The End of the Gloomy Source List

I’ve been spending most of my time in Yosemite for a while now. My favorite on-the-surface change is the change to source lists.

The sad-and-blue source list we’ve had for years — first seen in iTunes, iLife, and Mail — has been replaced with a translucent source list. It’s more fun, and I think people are going to love it.

But me, I’m ultra-sensitive to on-screen clutter. (It’s a flaw.) I almost never have files on my desktop. There are relatively few icons in my Dock compared to other people (around 12). I hide apps that are not in active use — at most I’ll have Xcode, Terminal, and Vesper for Mac showing. My desktop background is always a solid color.

So I turn off source list translucency, via System Preferences > Accessibility > Display > Reduce Transparency.

And it looks great. Source lists are a nice very light gray, rather than that wiped-out blue we’re used to.

When I have to go back to 10.9, and have to deal with the old-style source list (in Xcode, especially), I can’t wait to get back to Yosemite.

I’m surprised by how much of a difference this makes to me. It’s a big deal.

Update a few minutes later:

William Van Hecke posts on Twitter:

We’ve long called that sidebar color “corpse blue” around here. It’ll be sad to lose that bit o’ jargon.

New Database

Realm is a new mobile database that I should look at.

While there are many options for server-side databases, for mobile it’s pretty much SQLite. (Core Data uses SQLite.) A few people may be using LevelDB (which I’ve been meaning to look at). Perhaps some people are using Kyoto Cabinet.

I love SQLite. I’ve been using it since SQLite 2.something. I’ve just about made a career out of it.

But if you asked me if we mobile developers should have more options, I’d respond with an emphatic yes.

A Stock Control Won’t Always Do the Job

I wrote about using stock and custom controls the other day, and I was careful to make the point that sometime custom controls are absolutely needed.

Vesper has a bunch of custom controls — far more than in any app I’ve made before. We could probably cut out a few of them, especially now that iOS 7 and 8 added features that we didn’t have when Vesper was first created, but we can’t cut all of them, or even half.

Here’s a small example:

If you’re a Vesper user, you know that tags sit above the keyboard when you’re editing. When you’re not editing, they appear below the end of the text.

The tags move as the keyboard appears and disappears.

You also know, if you’re a user, that tapping a tag gives you a little menu — much like the text editing menu — that lets you copy or remove a tag.

The tags themselves are a UIButton subclass. A fairly elaborate one, but still a UIButton.

That menu, though, is entirely custom. It’s not even a popover, since popovers won’t appear on iPhones until iOS 8. It’s a fake popover, custom from the ground up.

It seems like this is the perfect place to use UIMenuController. And, in fact, if you look at the menu (just tap on a tag to see it), you’ll see a black menu with white text, rounded edges, and an arrow pointing to the tag button.

It looks almost exactly like a UIMenuController menu, in other words. A normal, non-obsessed person wouldn’t notice the difference.

So why not switch to UIMenuController? Delete all that custom code. Great idea. (I love deleting code. Love love love.)

But UIMenuController wants the item attached to the menu — the tag button, in this case — to become first responder.

And, as soon as the button becomes first responder, the text view is no longer first responder, which means the keyboard falls away, and the tag buttons move so that they’re anchored at the end of the text. (And the UIMenuController menu shows and hides real quick, as if it’s been frightened by all the sudden activity.)

So we can’t use UIMenuController in this case.

We could do something entirely different — a UIActionSheet, for instance — but that would be a usability loss in this case. A UIMenuController-like-menu really is the best way to solve this problem.

Which means we have to use a custom control.

It’s possible that, in iOS 8, I could make it a real popover, but I’m not sure I’d have control I need over the appearance. (The corners have to be rounded just so, the arrow has to be the way it is, etc.)

Anyway. That’s show biz for ya.

Update 9:15 pm: Well, it’s possible to keep the keyboard up when using UIMenuController. See Jared Sinclair’s tweet.

I’m not sure that would actually work in my case, since it would hijack typing, which should go to the text view. (I say this without actually trying it, though.)

String Constants

Here’s my secret, or maybe my superpower, or maybe just me being lucky — I’ve never had a bug related to using a string literal when I should have used a constant.

But I have had bugs when I used the wrong string constant.

Here’s a line of code that just made the in-development app throw an exception:

NSArray *uniqueIDs = [syncNotes valueForKeyPath:​VSSyncNoteIDKey];

Looks good, right? But it’s wrong. I replaced it with this — and the bug was fixed:

NSArray *uniqueIDs = [syncNotes valueForKeyPath:​@"uniqueID"];

You’ve figured it out already, I’m sure — VSSyncNoteIDKey != @”uniqueID”. VSSyncNoteIDKey is @”noteID”, which is the server name for a note’s unique ID. The local storage name is uniqueID. And I picked the wrong one in that line of code.

The real way to fix it is this:

NSArray *uniqueIDs = [syncNotes valueForKeyPath:​VSUniqueIDKey];

(Which I changed it to after having to find the right constant for uniqueID.)

I know that using a string constant is the accepted best practice. And yet it still bugs me a little bit, since it’s an extra level of indirection when I’m writing and reading code. It’s harder to validate correctness when I have to look up each value — it’s easier when I can see with my eyes that the strings are correct.

I knew I wanted @”uniqueID” and could have typed that — yet I used VSSyncNoteIDKey (probably because that’s where autocomplete led me first, and it looked right).

I know the three knocks against using string literals:

  • It’s hard to spot typos by eye.

  • The compiler won’t catch errors.

  • If you make a change, you have to change it in multiple places.

But I’m exceptional at spotting typos. And I almost never have cause to change the value of a key. (And if I did, it’s not like it’s difficult. Project search works.)

The question is: do I want to be the one guy who does what every other developer in the world thinks is terrible?

What if I believe, honestly and with good reason, that my using string literals would make for fewer bugs during development?

You’re horrified right now, I know, and you kind of wish I hadn’t posted this. (Think of the children!)

Swift Reflection

When I wrote about Swift structs and valueForKey yesterday, I didn’t know of a way to get this behavior.

Then Jason Peebles posted a gist showing how to do it. (Don’t be blinded by the fact that it’s doing operator overloading. The body of the function is what’s important.)

Though it’s not documented in the Swift Standard Library Reference — and is subject to change, and could disappear entirely — Swift has a reflection API.

I wouldn’t build anything on it, myself. It’s one thing to use documented features knowing that they could change — but using undocumented features is just asking for trouble.

But still, it’s interesting.

The Objective-C runtime has methods for getting lists of properties and methods and other info about objects — but they’re C APIs and they use C types, so they’re not that nice to deal with.

And, given the general guideline that #import <objc/runtime.h> in production code is almost never a good idea — and given that Cocoa has valueForKey:, setValue:forKey:, performSelector:, and respondsToSelector: — the Objective-C reflection APIs are (as far as I can tell) rarely used.

This is by design, surely. And you can imagine why: using reflection is a great way for developers to have fun while making clever and hard-to-understand systems.

But here’s the thing: I want this. It has its uses. And, used well, it can make for simple and easy-to-understand systems that are easy to maintain.

I forget who said that Swift is a language that can use something like Core Data but where you couldn’t actually implement something like Core Data. You might have solid reasons for wanting to look at an object’s properties (to write a generic JSON serializer/de-serializer, for instance). You might want to be able to provide method implementations at runtime, as Core Data does with @dynamic properties in Objective-C.

If I had to guess, I’d say we won’t see much of this in 1.0. It’s an advanced feature, not very safe and very open to abuse, and Swift needs to focus on safety for its first release.

But before too long we’re going to need this stuff. That there’s a reflection API, however undocumented and likely to change, is a good sign.

Swift Structs and valueForKey

Though I’m not writing very much code in Swift, I’m writing a little — and my brain is running a background thread where it keeps thinking about Swift and how my designs will change with Swift.

One of the things that intrigues me is the idea that structs can be used in place of objects in some contexts. Structs make multi-threaded programming simpler, since they’re passed by value and tend to be immutable.

I came up with a good use case, but then I hit a snag.

API Code

When Vesper’s sync system gets a JSON reply from the server, it has to turn that JSON into an array of something usable, and then merge those something-usables with existing model objects (NSManagedObject-like objects), and create new model objects when there isn’t an existing object.

The something-usables could be structs instead of objects. They can be created in a background queue (so that the JSON-to-struct conversion happens off the main thread), and then passed to the main queue where they’re merged with existing model objects.

That they’re immutable is perfect. The structs don’t need to change — they’re just a representation of what the server provides. Only the model objects need to change.

The Snag

For every merge-able property there are really two properties, and there’s a simple naming convention.

For example, a note’s archived flag has two properties: archived and archivedModificationDate.

Merging works like this pseudo-code:

if existingObject.archivedModificationDate < serverObject.archivedModificationDate {
  existingObject.archived = serverObject.archived
  existingObject.archivedModificationDate = serverObject.archivedModificationDate
}

But the code doesn’t actually look like that. Instead of duplicating the above for each property, there’s a single method that takes server object, existing object, and property name as parameters. Then it uses valueForKey: on both server object and existing object. (It gets the key for the date value by adding “ModificationDate” to the property name.)

This turns merging a given property into a one-liner:

mergeProperty(existingObject, serverObject, "archived")

(At this point I could, but haven’t, specify an array of property-names-to-merge in a plist rather than in code. I’m partial to that kind of thing, since it allows me to write highly generic and reusable code.)

The snag: structs don’t respond to valueForKey

I fired up a new playground and create a simple struct. It worked fine — I could access values via dot notation.

Then I tried valueForKey — which didn’t work, as expected.

Because I’d written a bunch of JavaScript code lately, I also tried the following:

x["propertyName"]

And:

x.["propertyName"]

Neither of those worked, either — but how cool would that have been? And Swift-like, I think, to provide a syntax for KVC rather than force the use of valueForKey:.

Perhaps there is a way to do this right now, and I just don’t know about it. Totally possible. (Let me know on Twitter if that’s the case.)

If there’s not, then I can’t use structs in this case, no matter how much it makes sense.

And this is a case where Objective-C’s magnificent suppleness — which we app developers rely on, which we prize — should provide some direction for the future of Swift.

rdar://17652770

On Adding AppleScript Support

Me, writing in the latest objc.io: Making Your Mac App’s Data Scriptable:

Scripting isn’t a matter of automating button clicks; it’s about exposing the model layer to people who could use your app in their workflows.

While that’s usually a small minority of users, they’re power users — the kind of people who recommend apps to friends and family. They blog and tweet about apps, and people listen to them. They can be your app’s biggest evangelists.

Overall, the best reason to add scripting support is that it’s a matter of professionalism. But it doesn’t hurt that the effort is worth the reward.

The entire issue — Back to the Mac — is good. It includes articles by Craig Hockenberry, Gus Mueller, Daniel Eggert, and Florian Kugler.

Standard Controls

Five and even ten years ago, Mac developers would tell you that you can’t release a Mac app that uses standard controls with their standard appearance.

Mac users would look at iTunes and the iLife apps and expect something more like those — and it was impossible to get that look without lots of customization.

Those were the years of brushed metal, wood-grain bookshelves, iTunes-like custom scrollbars, and so on. It seemed as if developers weren’t going for delight so much as awe. Look at my smoke particle effects and weep, ye mortals.

I think this is changing. A big part — the hugest part — is Apple, with iOS 7 and Yosemite, moving back to consistency and to a design language that looks great, makes sense, and is used by the standard components.

* * *

There were always problems with creating custom components.

A big one is that accessibility — or inclusive design (Natalia Berdys’s phrase, which I like) — takes more effort. With standard components, you often have to do nothing to get great accessibility. But if you’re building from scratch, you have to do more work than just making it look cool.

Another is that custom components don’t track Apple’s changes and enhancements. One eye-opener: on a recent The Talk Show, my co-worker Dave Wiskus noted that NetNewsWire 3.2 on Yosemite has a translucent sidebar with the correct font, while most Mac apps don’t. This is entirely because the source list was pretty much a standard source list, not because I had some special foresight years ago.

Another example is the activity sheet on iOS. You could create your own (we did, in Vesper) — but you won’t be able to support extensions in iOS 8 if you do.

A big problem is the cost of all this development. It makes me think of a recent post by Luc Vandal on The Indie Life:

I have spoken with other successful developers and many told me the same: sales are generally down. They are still doing great but there are more and more competitors also taking a slice of the same pie.

It’s probably necessary for indies to make more than just one iPhone app. Do the same app on Macintosh. Maybe make a second or third app.

Not long ago this would have been very, very expensive — because we believed (rightly) that we had to do custom versions of all the things.

But now, I most emphatically suggest getting out of that mindset. Use standard components in the expected ways as much as possible. Create custom things only when absolutely needed.

My app Vesper has a bunch of custom UI. A ton, actually. Could we cut back and still provide a great experience without any impact on the character of the app? Absolutely. And this shows how much has changed since iOS 6 (when Vesper 1.0 shipped) and now.

The things to concentrate on are what an app does, how it works, how it feels to use it, and how responsive and fast it is — which does not include doing built-from-scratch components except when absolutely necessary.

And it is still necessary at times. I’m not saying it isn’t. I’m saying that the reflexive attitude that tells us that nothing can be standard needs to become something we remember and laugh at, like pet rocks and bell-bottom jeans.

Here’s how I think about this to myself: the Romantic era, which started with the Delicious Generation and became dominant with the early iPhone apps, has given way to the Modernist era. Grandiosity gives way to sleekness and honesty.

Phishing Attack That’s New to Me

I got a legitimate email from my bank saying that there had been suspicious login attempts and that they’re sending a new card.

I also got a couple phishing emails from what appeared to be my bank saying that there had been suspicious login attempts, and that I should login and clear things up.

Theory: this is deliberate and not a coincidence. The attacker deliberately triggered the suspicion of my bank and then sent email hoping I’d assume the phishing emails are also legitimate, since, after all, I did get a legitimate email.

Lettersapp.com Domain Auction for App Camp for Girls

I own lettersapp.com — but, since it was part of an open source project, it wouldn’t be right for me just to sell it and make a profit.

People have been asking if they could buy it. It’s not really fair for me to just sit on it, and it’s not really fair to pick a winner.

So I’m doing an auction. All of the money raised by the auction will go to App Camp for Girls.

The auction runs through July 15, 2014, 7 pm. Bid now! It’s a great domain name and a great cause.

Vesper Mac Diary #9 - Not Going to Pass Things Around

Having gone to the trouble of figuring out how to pass an NSManagedObjectContext (or equivalent) from app delegate out to an NSWindowController and its NSViewControllers, I think I’m not going to do it.

Or, not entirely.

The benefit of passing things around is less-tangled code, which promotes code reuse and testing and makes for easier maintenance.

But there are three things to consider:

  • Passing things around requires more code. It’s less simple than, for example, just calling NSApp.delegate.context.

  • I never reuse view controllers, and I don’t write tests for them. I might some day do automated UI testing, but that runs against the app, not against a view controller in isolation. (I do test other things.)

  • I’ve never had a case where a view controller wants something other than the global version of whatever-it-is.

I may sound like a short-sighted, non-OO monster at this point. Here are a couple mitigating points:

  • A view controller’s data source and helper objects should take a context (and whatever else) as an initWith parameter. And the data source and helper objects should be tested, and may very well be reused. So, even though a view controller may refer to NSApp.delegate.context, its (testable, reusable) helper objects won’t.

  • If I’m wrong, revising a view controller to take a passed-in context (or whatever) isn’t difficult.

So that’s there where I am. (Slowly and obsessively questioning everything, as usual.)

Vesper Mac Diary #8 - Figured Out How to Pass Things Around

Let’s pretend the app delegate creates an NSManagedObjectContext, and it needs to somehow pass that context to various NSViewControllers.

Since I’m using storyboards and everything loads automatically — all code-free — I don’t have a code path I can use to send the context around.

I could just cheat. I could use a bit of baling wire in the form of NSApp.delegate.​context to get that context from anywhere. I’ve done that kind of thing, and I’ll do it again, but I don’t like it. It’s wrong.

The real trick was going from the app delegate to that initial window. Here’s what I figured out:

  • App delegate has a lazy managedObjectContext property. Created on demand. (Can’t wait till applicationDid​FinishLaunching: to create the context, for instance, because that’s too late.)

  • NSWindowController subclass for the initial main window posts a window-loaded notification in awakeFromNib. The object of the notification needs to be that window controller.

  • App delegate watches for that window-loaded notification. When it gets it, it does the equivalent of notification.​object.​managedObjectContext = self.​managedObjectContext. That sets the context on the window controller.

  • The window controller can then pass the context on to its contentViewController, also a subclass. The content view controller can then decide which of its child view controllers need the context, and so on until finished.

I don’t love this. It means the window controller and its view controllers can’t really do their setup until they get that context. But it’s not terrible, and it follows the principle of messages-leafward/notifications-appward.

Vesper Mac Diary #7 - Making Work for Apple Engineers

Other OS X radars filed today:

rdar://17567938 - I’d like an Info.plist key that lets me opt-in to having my app crash on an unhandled exception.

rdar://17567914 - I’d like a modeless presentation segue, suitable for things like Preferences windows.

rdar://17567893 - I’d like an API allowing the app delegate to get a reference to the window that was opened at startup. (It’s do-able, but it’s not straightforward, and it’s an obvious thing to want.)

Vesper Mac Diary #6 - prepareForSegue bug, maybe

This is either a bug, a misunderstanding on my part, or an error on my part. Though I don’t know if this is a bug or not, I decided it was worth filing just in case it’s a bug.

(rdar://17567823.)

You can download the sample project: PrepareForSegueTest.zip.

Here’s what’s happening:

  • It’s an OS X app with a storyboard.

  • The window has a containment segue to an NSSplitViewController.

  • The NSSplitViewController has two containment segues, one for each split view item.

  • prepareForSegue:​sender: is not called on either the window controller subclass or split view controller subclass. I can verify that both subclasses are in fact used (via an NSLog in initWithCoder: in each).

Is prepareForSegue not meant to be called in these cases? I have little experience with storyboards until now, but I would have expected that it would always get called, since it may be necessary for a parent to set some properties on the child, and this seems to be the place to do it.

Vesper Mac Diary #5 - Storyboards and Passing Things Around

I want to pass things to window and view controllers in Vesper for Mac and I haven’t figured out the right way to do it.

Think of “things” as an NSManagedObjectContext, for the sake of picturing what I’m doing and why it’s important.

I’m using storyboards, so I can’t write custom init methods. Window and view controllers are created via nib-loading machinery. It’s not a document-based app.

How do I get an NSManagedObjectContext (for example) from my app delegate to the window and then to the view controllers that need it?

Maybe the question really is this: how does the app delegate know the main window has been opened?

It’s not available as NSApp.mainWindow during applicationDid​FinishLaunching: or during awakeFromNib. If the app delegate could know that a window’s been opened, it could set properties on its NSWindowController. Then the view controllers could get the context from the window controller. (View controllers don’t have a reference to the window controller, but they could get there via the responder chain.)

I suppose the thing to do is have the window controller post a notification during windowWillLoad. The app delegate would watch for that notification, then set the right properties on the window controller, which would then be available to the view controllers.

But that doesn’t feel right — it feels a bit sneaky. Hidden. Behind-the-back. But it’s the best thing I’ve come up with. There must be a better way.

What’s the better way?

Swift Strings

Ole Begemann writes about Strings in Swift:

Despite improved handling of Unicode, working with strings in Swift is still hard. This is more of a realization of the complexity of Unicode than a criticism of the language, though.

Two Butterflies

There is a pair of Western Tiger Swallowtails that returns to the pine tree in my neighbor’s yard every summer.

It can’t really be the same pair, year-after-year, but it seems like it. It’s always two. I love watching them fly around my back yard. I don’t know what they’re doing, but it looks like they’re playing.

* * *

The closest thing to paradise might be the Pacific Science Center’s tropical butterfly house. You walk in and there are all these butterflies.

Sponsorships Available

We have some openings for sponsorships coming up, including the week starting Monday, July 7. If you’re interested in reaching Mac and iOS developers and power users — smart people always on the lookout for cool things and cool services — then get in touch with me.

More info — how it works, how much it costs, what weeks are available — appears on the Sponsorship page.

Vesper Sync Diary #19 - Intermediate Objects

In the shipping version of Vesper, VSNote, VSTag, and VSAttachment objects can convert to JSON directly. When sending objects to the server, it fetches from the database, then gets the JSON representation of each object (as a dictionary) and sends those (as JSON data).

That’s pretty reasonable, I think.

The thing I like less about the shipping version is how it handles JSON responses from the server. It calls merge routines which compare JSON dictionaries to existing objects. When an object is new it creates a new model object based on the dictionary.

I don’t like this because working with JSON dictionaries is a pain, and it was a source of bugs during development. There are three main issues:

  • A value might be NSNull</code> rather than the expected string or whatever, and the merge code had to watch out for this.

  • A date value is a string, and the merge code had to deal with converting strings to dates.

  • The merge routines use dictionary literal syntax, which is an improvement over objectForKey:, but it’s still less clean and harder to read than accessing properties (such as syncNote.text).

So what happened is that the merge code is really doing two things: 1) converting JSON values to expected types and validating values, and 2) doing the actual merging.

The change I’m making right now is to make these two steps more explicit. It comes at a small cost, but not something a user would ever perceive, so it’s fine. (I’m a mad stickler for performance, and Vesper is praised for being fast — it will remain fast.)

I’m introducing three new classes — VSSyncNote, VSSyncTag, and VSSyncAttachment — which all inherit (ugh) from VSSyncObject.

These classes do the following:

  • Init themselves with a model object.

  • Init themselves with a JSON representation from the server.

  • Generate a JSON representation to the send to the server.

These classes watch for NSNull values and turn those to nils. They handle date conversions.

On Sending to the Server

Instead of doing a fetch request and turning model objects directly to JSON objects, the conversion will go model object -> VSSyncObject -> JSON. Yes, that’s extra work, but not noticeably extra, and it centralizes all the conversion knowledge in the sync object.

On Handing Responses from the Server

The conversion will go from JSON -> VSSyncObject. Then the merge routines will compare model objects to VSSyncObjects, rather than to JSON.

This means that the merge routines will not have to worry about NSNull and dates-as-strings — all that work will have been done before the merge happens, in the various sync objects.

What I Like About All This

It makes for more testable code. For instance, I can test JSON validation and type conversions without having to run the merge code.

Another thing I like: conversion to/from JSON can happen on a background queue. Right now this is all on the main thread, since the actual model objects, which are main-thread-only, are involved. (So, in the end, it may be that this change makes Vesper feel even faster, since more work is shuffled to the background.)

But the main thing is cleaner code. The merge routines work and I know they work — they have tests, yes — but every time I look at them it’s hard to see the logic past all the JSON-handling and dictionary access. This way the logic will be made perfectly clear — and, since this is a super-critical part of the app, it should read like a smart kindergardener wrote it. (Which is exactly how I want all my code to look, come to think of it.)

Vesper Sync Diary #18 - Where the API Logic Lives

(This isn’t really a diary anymore — I’m just explaining things already written. But I might as well make this part of the same group of posts.)

On Twitter, Lee Morgan asked me:

…suggestion for where API logic lives? in Model? ViewController? an API class?

Here’s where everything goes:

The VSAccount object is the top-level object for syncing. It has username and password; it has methods for creating an account, logging in and out, and syncing. The VSAccount object exists whether or not the user has an actual account and is logged-in. It also knows about the app’s data model.

The VSAccount object knows about the VSAPICaller object (it’s the only thing that knows about it). The VSAPICaller object has methods for each of the different calls that go to the server. It has an NSURLSession and a queue. VSAPICaller doesn’t know about the account or any of its state — its methods take parameters sent from VSAccount. It also doesn’t know about the app’s data model (it gets JSON objects from VSAccount).

The VSAPICaller object creates VSAPICall objects, which are conceptually like NSOperation subclasses (though they’re not). A VSAPICall object creates the NSURLSessionDataTask and handles things like expired authentication tokens.

There are some delegates and blocks in all this. Most notably, VSAPICall calls back to VSAPICaller, and then VSAPICaller calls back to VSAccount, when an API call completes. The callbacks all take a VSAPIResult object, which includes properties such as the request, response, error, statusCode, parsed JSON object, raw response data, and so on. This way, when VSAccount gets a response, it can look at everything: there’s nothing hidden from it.

Syncing is triggered by a number of different things. For things like the app launching and coming to the front, for an account being created, for notes being edited, there are notification observers in VSAccount which call the sync method.

Other callers can directly tell VSAccount to sync, but none do. (Since it’s not needed, I should remove that method from the .h file.)

Calls to the sync method are coalesced: the method can get called a bunch of times in a row, and it will run just once after a delay of two seconds after the last call.

When data is returned from the server, VSAccount uses two other objects, VSSyncNoteMerger and VSSyncTagMerger, to merge server data and local data. Those two objects understand the JSON the server returns and they know about the data model, and they create and update local objects as needed.

The model objects don’t know anything about API calls or syncing. (They can turn themselves into JSON and back again, but I’m working on changing that to use a separate intermediate object instead. I have good reasons for this.)

Model objects do however have to differentiate between user changes and syncing changes.

Consider what happens when a user archives a note: the archived flag is set to YES, the archivedModificationDate is set to the current date, and the note’s local modification date is set to the current date. (The query that gets notes to send to the server looks at the local modification date.)

But if the sync system marks a note as archived, it should set the archived flag to YES and it should make archivedModificationDate the same as what the server says it is. It should not change the local modification date, since that would just cause the sync system to send the note to the server again when it doesn’t need to.

This is a pain, because it means that the model objects have to have methods like userDidMarkAsArchived: which do the right thing. (The sync system just accesses properties directly.) If there were a better alternative, I’d use it, but I don’t know what that would be.

What I Like About All This

I like my model objects to be dumb containers for properties. They are, after all, just an objectified version of a database row, and I like to keep them that way, as much as possible.

I also like to keep my view controllers free of any syncing or API logic. Instead, they make changes to the model and react to changes — they don’t need to know that the changes came from a sync versus a user change.

The only view controllers that need to know about the server are the view controllers in the UI for creating an account, signing in, and so on. Those view controllers may need to display an error or dismiss a view controller (etc.) based on the result of an API call.

But, importantly, and worth stressing: those view controllers don’t actually know how to make the call to the server — they just know how to call createAccount:password:callback: and similar VSAccount methods.

…is People!

Apple, that is. Says Allen Pike.

With the WWDC NDA lifted, other Apple employees, from the creator of Swift to various API maintainers, took to Twitter to gather feedback on all the goodies they’d dumped on developers. In the web community this would be expected behaviour. In the Apple community, it’s a delight.

Vesper Sync Diary #17 - The Problem of Relationships

While I was talking with some folks yesterday about syncing-in-general, the issue of relationships and incomplete object graphs came up, and I realized I hadn’t written about it.

Here’s the problem: an object with relationships to other objects may have been synced — but those related objects haven’t been synced yet.

In other words, in Vesper terms, a note may have been synced, but its tags and attachment metadata haven’t been synced yet. How do you deal with this?

Answer: you design the system so that this doesn’t happen.

In general this means that when an object is sent to the server, and when an object is returned from the server, its related objects are also included.

In Vesper’s case, when it sends notes to the server it also includes attachment metadata and the names of its tags (in order).

Even though local storage has three separate tables (notes, tags, attachment metadata), there’s nothing that says we can’t add related objects to the JSON version of a note.

Attachment metadata objects are included in their entirety (uniqueID, mimeType, height, width), but we cheat a little bit with tags: we include their names only. But since a tag’s unique ID is the lower-case version of its name, a client can create a tag object with just its name.

I’ve considered a different (but similar) solution. Instead of separate calls for syncing tags and notes, there could be just one call. The client would send two arrays in that one call: one array of changed tags, one of changed notes. The response from the server would be in the same format, and the tags array would include every changed tag and every tag related to a note in the notes array.

But the current system is working well, and the only real reason to change is to cut down the number of API calls. (Number of API calls isn’t a problem for us, either on client or server — Vesper syncing is already fast and efficient. But I don’t mind improving on things that are already good.)