Jun 2014

[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 Mac Diary #4 - Reporting Bugs

Last summer I worked on Vesper for iOS 7 using the iOS 7 betas. And I was busy, and we had a deadline (iOS 7’s ship date, which we probably didn’t actually know precisely) — and I didn’t bother to report bugs until after iOS 7 shipped.

Which was a mistake.

In fact, my attitude with other iOS and OS X releases has always been to wait and get a near-finished beta and deal with whatever needs dealing with. That works fine most of the time.

But last year I could have reported some important bugs which might — might — have been fixed in time for the iOS 7 release. Or perhaps they’d have been fixed in a subsequent update.

While I’m not responsible for another company’s bugs, I have changed my attitude about this. It doesn’t matter how busy I am, I’m going to report everything I notice, whether small or large.

And the reason is self-serving: the bugs I find are the bugs that affect my apps, and I dearly want those bugs not to exist. If the only way I can help is to report bugs, then I’ll report bugs.

I’ve reported a few today. Here’s another one with a sample project: ToolbarSpacer.zip. Toolbar items that are single-segment NSSegmentedControl objects get extra space to the right. Note that the label isn’t centered, and clicking on the apparently blank space doesn’t move the window. (Xcode 6 beta 2. Latest 10.10.) (rdar://17501552.)

Vesper Mac Diary #3 - Hiding Window Title

I wanted to try that new thing where you can hide the window’s title bar.

I have a window with a toolbar in a storyboard, so the first place I looked was in Interface Builder. I didn’t see anything there for setting this property.

No big deal. (rdar://17501388.) Some things don’t make into IB, or they make it later on. Easy enough to do in code.

So I created an NSWindowController subclass and assigned it to the window controller in my storyboard.

Then in windowDidLoad I added the following line:

self.window.​titleVisibility = NSWindowTitleHidden;

That should do it. But it didn’t — windowDidLoad doesn’t get called. (At least for storyboards, or at least for this one.) (rdar://17501206.)

Next I created an awakeFromNib method and added that same line of code there. It worked! In case you’re wondering how to do this, now you know.

Special note about Swift

I’m not writing code in Swift, just because when things go wrong — as they did above — using Swift adds an additional element of uncertainty, since Swift isn’t shipping yet.

(I wish I were writing in Swift, because it looks like fun. I’ll wait.)

But I did make a classic mistake right at first:

self.window.​titleVisibility = NO;

This translates to self.window.​titleVisibility = NSWindowTitleVisible;, which is not what I meant.

Would Swift have caught this bug for me? I suspect it would have.

Sale on Mac Apps for Writers

Tinderbox: SummerFest 2014:

We’ve gotten together with some of the best makers of artisanal software to make Tinderbox better – and to make our tools work together even more smoothly. And now that we’ve all finished our latest updates, we’re working together to save you lots of money.

Save 25% on Tinderbox Six, Scrivener, Aeon Timeline, Nisus Writer Pro, and DEVONthink Pro.

Vesper Mac Diary #2 - Setting Swift Aside for Now

I’ve been writing Swift code. Not a ton yet. Probably not even 100 lines. I wanted to write all the new code for Vesper for Mac using Swift — but I realized today that it’s just too soon and I was too optimistic.

I like Swift. I’m not good at it yet, but I like it. A lot.

But here’s what happens:

Something goes wrong. I wonder if it’s a Swift bug. I wonder if it’s because I’m not a Swift expert yet. I wonder if it’s because I’m doing something (AppKit) I haven’t done in a while. I wonder if it’s a combination of two or more of the above.

I end up spending too much time this way, when I could move more quickly and with much less uncertainty when things go wrong if I stick for now with Objective-C.

This is not how I wanted it to go.

This isn’t a criticism of Swift, by the way — it’s not shipping, after all, and bumpiness is expected.

It’s just that I’m 14 years old at heart, and I really wanted to have fun rather than have to make a cold professional decision.

Well, there’s this: I was just being greedy. Writing Mac apps is so much fun that it doesn’t matter that I don’t get to use Swift yet.

Happy Friends

Dave Winer: Getting Started with Happy Friends.

It’s a browser-based outliner that shows tweets from the people you follow that you add to the list.

A Few Small Tips

Things you may not know:

To move any window without making it active, hold down the command key and drag its title bar.

To paste the path to a file you’re editing into Terminal, drag its proxy icon from the title bar to Terminal.

You probably know you can use ctrl-A and ctrl-E to navigate to the beginning and end of the current line in Terminal — but you can also navigate by word using option-leftArrow and option-rightArrow.

cmd-E copies selected text to the system-wide search pasteboard.

You can pop up Xcode’s methods list menu with a keystroke — and then start typing to filter down to the method you’re looking for. Makes it easy to navigate without searching or using the mouse.

[Sponsor] Microsoft Azure Mobile Services

Microsoft Azure Mobile Services provides a scalable and secure backend that can be used to power apps on any platform — iOS, Android, Windows, or Mac.

With Mobile Services, it’s easy to store app data in the cloud, authenticate users, and send push notifications.

Built from the ground up to be flexible and extensible, Mobile Services lets you code your app backend in C# or Node.js. You can save app data either on-premises or in Azure SQL database, blob storage, table storage, and MongoDB.

Swift + JSON Again

David Owens II finds that handling JSON in Swift might be pretty cool after all.

App Architecture

Ole Begemann writes about Appleʼs Take on App Architecture and session 232, which was presented by local-to-us Apple developer Jeff Watkins. (He comes to Xcoders sometimes.)

Mike on Swift

Mike Ash writes the first Friday Q&A about Swift: Interesting Swift Features. He covers optionals, tuples, generics, type inference, structs, trailing closures, and operator overloading.

NSViewController Changes

iOS developers outnumber Mac developers, surely, and I wouldn’t be surprised if it’s more than one order of magnitude.

That should change. iOS developers ought to know that writing Mac software is fun, and Mac apps can make real money.

One of the unsung, or not-sung-enough, set of changes announced at the recent WWDC is a change to how view controllers work on Macs.

Starting with Yosemite:

  • Storyboards are supported on Macs, and are now the recommended way of building your UI.

  • View controllers — NSViewController objects — are now placed in the responder chain. (Previously we had to manually place them in the responder chain.)

  • The NSViewController API is now very similar to the UIViewController API. It would be instantly familiar to any iOS developer.

  • NSViewController has support for containment, with some built-in containers (split views, tab views) and the ability to write custom containers.

Macs already had Auto Layout support, and of course lots of frameworks such as Foundation and Core Data are Mac frameworks too. (Often they were originally Mac frameworks.)

The weirdest thing for iOS developers doing a Mac app was probably the old way of doing outlines and table views — there was that old NSCell API. But we’ve had view-based tables and outlines for a while now, so that’s not a consideration any more.

And the Mac has some nice things that don’t exist on iOS. For instance, wiring up a checkbox in a preferences screen to NSUserDefaults requires no code whatsoever, since you have Cocoa bindings on the Mac.

You might not want to write Mac apps. That’s fine. But AppKit has just taken some very nice ideas from UIKit, and that’s a cool thing, and worth noting.

Dave on Frontier

In Thinking out loud about Frontier, Dave Winer suggests porting the database code to JavaScript.

I hadn’t thought of that. It would probably be faster than you think. The bottleneck should be reading from and writing to disk, not the speed of the code itself.

Chuck Shotton (author of MacHTTP and WebSTAR) has a good comment on Dave’s post. Part of it:

The major value proposition is the tight integration of persistent data store within the name space of the embedded scripting language and the ability to store and execute code from that database…

The productivity gains are enormous, being able to write in a widely supported language using an easily-exported data model. For some reason, no one has really replicated the Frontier model using modern software stacks.

Shared Toolbar Items

In The Hit List Diary #2, Mike Abdullah presents a way for multiple view controllers to share toolbar items, so that the shared items stay constant — instead of fading in and out — on transitions.

Tom on CloudKit

Moves like Azure:

In contrast CloudKit is not actually a sync mechanism. Instead it’s a transfer mechanism, where your app must explicitly initiate all data transfers.…

This all means that using CloudKit in an app will more closely resemble third party cloud solutions like Azure or Parse.

As a result, using CloudKit will likely mean more code in your app than using iCloud with Core Data. On the other hand, CloudKit’s more direct and less magical approach to dealing with cloud-based data should be more reliable.

Mobile Services’s HTTP API

I got an email this morning asking me about using Azure Mobile Services from the Mac.

Here’s the thing: Mobile Services provides an open source SDK with iOS support but without Mac support.

Given that the name is Mobile Services that’s not a complete surprise. However, it’s no stretch to imagine that you’d want to use these services on a Mac too, as we do with Vesper.

I haven’t spent much time with the framework, but it appears to be good. It includes some very nice things, such as support for querying the server using NSPredicate.

Instead — because I knew we’d be doing a Mac version — I wrote my own code for talking to the server. It was ridiculously easy.

Mobile Services is a hosted Node.js service with a bunch of yummy sugar on top. The thing to know is that that sugar doesn’t get in the way of calling web services the same way you’re used to.

How to Call a Mobile Services Endpoint

Most of the time, if not all the time, you’ll be passing JSON to an endpoint and getting JSON back.

So you have to do the right things with the JSON, just as with any other server: serialize it to NSData, setHTTPBody, and set the Content-Type header to application/json. And you’ll have to turn the response data into a JSON object and then do the right things with that JSON.

For any endpoint that requires the application key (which is any level except for the “Everyone” level), you have to add your public app key to your request headers.

It’s as simple as this:

[request setValue:​@"your_public_app_key" forHTTPHeaderField:​@"x-zumo-application"];

(I’ve never asked, but I assume zumo is short for aZUre MObile.)

For any endpoint that requires user authentication, you need to add the user’s JWT authentication token that the server provides on login:

[request setValue:​authentication​Token forHTTPHeaderField:​@"x-zumo-auth"];

Getting the URL of an endpoint is pretty simple. For the table-based calls, I think the prefix is “table.” (I’m 99% sure.)

We use custom API exclusively with Vesper, and the prefix is “api.”

So, to construct a URL, take your service name, add the prefix, then add the name of the endpoint. As in: https://coolservice.​azure-mobile.net/​api/​myendpoint.

(Because it’s a Node service that uses the Express router, you can create longer URLs — such as /api/myendpoint/foo/bar?a=b — but you don’t have to. API design is up to you.)

Now: the one thing that could be a challenge with a Mac version is if you’re using Twitter or Facebook as identity provider. We’re not doing that — we wrote our own accounts system, using this code as our starting point — because we found that people get nervous that Twitter or Facebook might have access to their data. (They don’t, but that’s a hard thing to explain.)

So, if you’re using Twitter/Facebook login, you’ll have to figure that out — but you have the iOS Mobile Services SDK to guide you. It’s work, but there’s nothing magical about it: it should be figure-out-able.

C# in Sheep’s Clothing

David Owens II has some criticisms of Swift. Swift is not exactly Objective-C without the C — it’s less dynamic, and more like C++ or C# in some respects.

(Via Michael Tsai. If you’re a developer, you need to subscribe to Michael’s feed.)

My suspicion: after a while, good Cocoa developers will use Swift most of the time, but we’ll have figured out the cases where using Objective-C makes sense. For instance: dealing with JSON, which is one of David’s examples, may be one of those places where Objective-C is the best tool for the job.

Maybe it’s like this: when things are orderly, Swift is perfect. When order needs to be made from chaos — such as when talking to web services — then Objective-C comes in to make order from that chaos, and then it passes off orderly objects to Swift code.

Experienced Cocoa developers will figure this out and won’t even have to think about when to use which language. The fact that we have both, and can use both languages in a single app, will come to be seen as a strength of the platform.

Mike on Storyboards

Mike Abdullah, in The Hit List Diary #1, discusses merging storyboards. Which is going mostly pretty well.

Vesper Update

Vesper 2.001 is up on the App Store — and we’re celebrating our first year with a sale: just $2.99.

Post-WWDC Thoughts on Rebooting Frontier

(Note: this is all thought experiment. I have no idea if anything will ever get done.)

I’ve got Sal’s presentation on JavaScript for Automation playing right now. It seems obvious to me that that’s the language.

But I’m mainly thinking about the highest level. What are Frontier’s core virtues?

  • Easy persistence in a hierarchical database with a GUI browser that has great navigation.

  • One central location (an app) with quick access to your database, scripts, scheduled scripts, suites of scripts, static websites, and dynamic websites and web services.

  • Extendable and scriptable UI. A suite can add a menu, for instance.

  • Development and runtime environments are the same thing.

There are plenty of cool things about Frontier that aren’t strictly required. Do scripts have to be written in an outliner? No. It’s a cool thing, but it’s not critical. Scripts don’t even have to live in the database — in fact, it might be better if they didn’t. Keep the database to data only. What is critical is that the app makes viewing and editing scripts convenient and easy, and it’s just as easy to see the data that scripts work with, side-by-side with the scripts themselves.

Back to high-level thinking. I’m thinking about File > New. What might a scriptor need to create?

  • Quick script: a disposable one-line (or few-line) script.

  • Simple script: a one-file script that does a thing. You’d want to get back to it and run it any time.

  • Suite: a set of related scripts. A mini-app.

  • Library: a set of related scripts that other scripts can call. Might be a scripting interface to another app, might be commands that drive a server, might be wrappers for some Cocoa APIs, etc.

  • Scheduled script: runs periodically. Probably calls into a suite or a library.

  • Static website: a set of data and scripts that is turned into a website by a static website rendering suite.

  • Dynamic website/web-services: a set of data and scripts that is turned into a website (and/or API endpoints) by a dynamic website rendering suite.

The thing is, these aren’t necessarily discrete things. You might want to build a system with a library, a scheduled script, and a dynamic website (for instance). Imagine a local RSS reader: it has an RSS parsing library, an RSS storage library, a scheduled script that downloads a bunch of feeds, and a dynamic website that provides the feed-reading UI.

The app should encourage developing in layers, but it should also make it easy to associate these layers, so you can work on that RSS reader (for instance) as a whole.

The other thing is, sometimes you really do just want to create a library or static website or whatever. But then later you might want to add a scheduled script to your website (for instance), and you’ll want those things to be associated.

In later years Frontier developed a higher-level system of Tools. Tools could contain all of these things.

The name “Tools” is Windows-y and isn’t great for a Mac app. (Which is, no question, what I’m thinking about. I have zero interest in writing for Windows or Linux.) In the year 2014 I think we just use the name “App” for something like this, even though it’s a bit of overloading. I’d argue that it’s the approachable and understandable name.

So your choices would be:

File > New > App
File > New > Script
File > New > Scheduled Script

The UI for your app would allow you to add and edit a library of scripts, scheduled scripts, menu, static website, and dynamic website. Each part would be optional.

But there’s a different approach I could take instead, a project-based approach. In this case an app is more like an IDE project, and you can add things — new things and existing things — to the project.

Consider the scenario where you have multiple apps that use the same RSS parser library. You’d want that library associated with each app, rather than just owned by a single app.

So maybe it would be:

File > New > Project
File > New > Library
File > New > Script
File > New > Scheduled Script
File > New > Static Website
File > New > Dynamic Website

After creating a thing, you can add it to one or more projects.

This makes a project much looser than an app: it’s really just a UI thing, a visible, clickable, navigable organization of separate things. And that makes packaging and distribution more difficult, where an app would be a contained thing and easier to distribute.

I don’t know. Still thinking.

But I’m convinced — in part because people keep coming up to me and telling me so — that there’s a value in File > New > Thing That I Want to Make.

[Sponsor] Microsoft Azure Mobile Services

Microsoft Azure Mobile Services provides a scalable and secure backend that can be used to power apps on any platform — iOS, Android, Windows, or Mac.

With Mobile Services, it’s easy to store app data in the cloud, authenticate users, and send push notifications.

Built from the ground up to be flexible and extensible, Mobile Services lets you code your app backend in C# or Node.js. You can save app data either on-premises or in Azure SQL database, blob storage, table storage, and MongoDB.

Vesper Testing

I want nothing more than to dive into Vesper for Mac and write Swift code and work on a great Yosemite app — but I’m doing testing instead.

The server-side testing is wonderful. Almost everything is testable — and when a function isn’t easily testable, at least I can write a test for everything it calls. I totally get all the emphasis on testing I notice in the Ruby and JavaScript communities.

And I can even see why I might want to write tests first. (Maybe. Sometimes.)

Man, JavaScript, sheesh

I write JavaScript code like an Objective-C programmer. Say I want to change the parameters to a function — add one, change parameter order, whatever. I expect the compiler to tell me that now I have errors in every place where that function is called.

But, of course, that doesn’t happen. Sometimes I think I could do almost anything to my code and it would still compile. (Which marks an advancement in proficiency. At first it was a struggle to write JavaScript code that would compile at all.)

This happy-go-lucky compiler drives me crazy. But this is also where testing comes in — some one or more tests should fail after I edit parameters to a function. While that’s not as handy as the compiler telling me in the first place about errors and exactly what and where they are, it’s infinitely better than not knowing anything.

(And this is why I wish for Node.swift. Or for Mobile Services to support TypeScript, which is, very roughly, JavaSwift.)

Testing isn’t just to catch errors a compiler would have caught, of course. But it does that too, and the more tests I have the less time I spend trying to figure out what just went wrong.

Man, GUI apps, sheesh

The other day — not in shipping code:

I fixed a bug. Released to beta testers. That bug fix caused another bug. I fixed that bug. Released to beta testers. That bug fix caused another bug. I fixed that bug. Released to beta testers. (It’s good now.)

Could I have written unit tests for any of these bugs? Nope. They were all in view controller code, and they required user input.

(Yes, I’m aware that I’m wrong. But creating and maintaining automated UI tests is such a pain still that I consider it not worth it. One day that may change.)

While the API server is about 2,000 lines of code and almost all testable, the iOS app is about 35,000 lines of code, and very little of it is testable.

Luckily, it’s possible to test the most critical parts: data migration and syncing. And I’ve written tests for these. But there are about 25,000 lines of UI code (estimated; I kind of think it’s higher) that need manual testing.

(Vesper is probably the smallest app I’ve worked on. And yet I still find myself staring at the project’s sidebar, looking for any way I can delete some code.)

So I’m spending today sweating vinegar as I try to control my impulse to get going on all the shiny new fun stuff — instead, I’m writing a many-hundreds-of-lines-long manual testing recipe. (Which I should probably have done a year ago, yes, but better now than going another year.)

I’ve broken it into two parts: pre-beta-release tests, and pre-App-Store tests. By the time I’m finished, the longer of the two should be pre-beta-release tests.

This is a massively boring thing to do. And it’s going to be boring to step through the recipe every time, too.

But you know what? Every one of those three bugs would have been found by my testing recipe, and they would never have been seen by beta testers if I had stepped through the tests.

If I’m not willing to buy quality with boredom, then I’m in the wrong business.

Well. Back to it. And after that it’s back to writing server tests. And then — then, finally — Mac app + Swift. My reward.

Spilled Some Old Beans

If you missed The Record Special #2 — where Chris interviews me — you missed me talking about Microsoft wanting to buy NetNewsWire.

(It came out right before WWDC, so it was easy to miss.)

Safari + RSS

One of the small surprises to me in the Yosemite update is that Safari supports RSS again.

It’s not the same as it used to be, but it’s there. Links show up in the Safari sidebar.

I think this is cool.

* * *

I remember the WWDC keynote when Safari/RSS was announced. I had been worried about an Apple RSS reader the year before, and I was worried again that year.

And then there it was. And right in the browser. So I figured my app NetNewsWire was screwed — off to meet Watson, wherever the hell it went.

But was sitting next to Daniel Steinberg. I don’t remember exactly what he said — something simple like “Oh, I think you’ll be fine” — and I believed him, right then and there, even as Safari/RSS was rolling out.

Now there’s a guy who’s good at being reassuring. I’m not sure anyone else could have handled me that day.

And he was right. NetNewsWire sales doubled when Safari/RSS came out. I think it was the best possible thing for my app, that Apple gave RSS a kind of seal-of-approval and let millions of people know that the technology existed.

And so, for nostalgic reasons, I’m pleased to see Safari pick up RSS again.

* * *

Later that same WWDC I talked to an Apple engineer who explained to me that there had been quite a bit of discussion over whether or not to include a “Don’t be evil” popup in Safari’s preferences. (Her words.) That popup allowed a user to choose their default RSS reader, so it wouldn’t have to be Safari and could be something else.

To this day I remain grateful to the people who argued for the right side of that argument. I don’t even know their names, but I wish them all the best.

Question for Core Data Users on Testing

I’m exercising some measure of self-discipline and writing more tests (for both iOS app and server) before I allow myself to make any potentially breaking changes. (I’d rather be writing Swift code for my Mac app. But it can wait.)

One of the things I’m testing is JSON serialization and de-serialization for VSTag and VSNote objects.

I wondered how you’d do this in Core Data. I’m asking earnestly, because I don’t know and I’d like to know, because I strongly suspect (contra the opinion of everybody who knows me) that I’ll be using Core Data some day.

Here’s what I do right now:

  • Alloc/init a VSTag object. Set some properties.

  • Get a dictionary from its JSONRepresentation method.

  • XCTAssert that the values in the dictionary are as expected.

(The process for the reverse is as expected. Create dictionary, call the method that creates a VSTag object with the dictionary, then XCTAssert that the VSTag’s properties are as expected.)

Note that I don’t have to set up a Core Data stack. The VSTag object doesn’t get saved anywhere. It’s just a plain old object that goes away at the end of the test, without persisting.

If you’re using Core Data, what do you do for these kinds of tests where you need model objects but you don’t want to save them?

Update: the answer comes from Colin Cornaby:

Create a special test store, save there. Also tests your schema validation. Or use in memory store.

Core Data Thoughts - June 2014

I’ve been thinking about Core Data since WWDC 2014. I had three feature requests filed with Apple — one each for batch updates, batch deletes, and asynchronous fetches.

They did two of three: batch updates and asynchronous fetches. That’s huge.

Nevertheless, it’s still possible to prefer an alternate data layer — but I think it’s harder to justify an alternate model layer.

There are some things I prefer about my own system.

I like that in my system model objects are always main thread objects and all database access is on a background queue, so that the main thread is never, ever blocked. This takes care of concurrency and UI responsiveness issues.

You might say that smart use of Core Data would amount to just about the same thing, and I’d reply that I’m not going to be smart all the time, and so I design my data layer so that it takes care of me when I’m dumb.

I also like that, in my system, model objects aren’t necessarily tied to the database. In Vesper I have VSNote objects where changes get saved and VSNote objects that are detached from the database. One use of this is in syncing: I can generate detached VSNote objects from incoming JSON, and compare those to VSNote objects tied to the database. It’s nice not to have two separate classes.

I like that the IDs for my objects are also primary keys and are defined by me. This matters when dealing with data coming from the web.

I also like using SQL directly. Core Data adds a layer between me and what I want the database to do — and it’s easier for me just to tell the database what to do. Cut out the middle-man.

Here’s an example: I have a query that lets Vesper know if there is at least one unarchived note without a tag. I don’t want the note — I just want a boolean. My query is straightforward and looks like this:

select 1 from notes where archived=0 and uniqueID not in (select distinct noteID from tagsNotesLookup) limit 1;

The Core Data equivalent would be a fetch request that gets any note where tags is nil and archived is NO, limited to one object. While I can write the SQL almost without thinking, I’d have to look up how to write the NSPredicate. (Yes, that’s on me, but I’m talking about personal preferences here.)

At some point these things are outweighed by the need to write and maintain less code. They’re outweighed by the possibility that another person might work on the code, and that person is likely to know Core Data, and will certainly not know my custom system.

If Core Data can do the job, and do it very well, then it’s hard to justify not using it, despite my personal preferences.

That said, it would be dumb for me to take the time to rewrite Vesper’s data layer: it’s working code, and it’s fast, and I’m happy with it.

But were I to start something new, I would use Core Data.

Dreaming

I can’t help but think that it might be time for the Core Data team to do a fresh start. Core Data is about ten years old, and it pre-dates GCD and blocks and iOS. While it has adapted well over the years, it’s still a big framework with far more power than any one app will ever use.

Were I starting over, I’d do something lighter — much like Vesper’s system. Something like this:

  • Model objects on main thread only. Detached model objects on any thread.

  • Database access is async. Background serial queue. No merge policies, because they’re not needed.

  • No saving, because changes are streamed to the database. Undo support is left to the developer.

  • SQLite only.

  • Object IDs are primary keys and are developer-defined. (Since those IDs often come from web services.)

  • Wouldn’t shy away from calling itself a database system, because that’s what it would be. It might even allow arbitrary SQL, though NSPredicate would be preferred in general.

  • Would retain important features such as object uniquing. The main thread object cache would keep live objects in sync with what’s in the database. Change notifications of some kind are generated. Would handle relationships. Would use the same (or similar) data modeler that Core Data uses.

This is closer to the metal in the way CloudKit is closer to the metal — which is a virtue of CloudKit.

The biggest challenge in the above is faulting. I would limit this to relationships, so that one simple query can’t trigger cascading queries that end up reading in way more objects than are needed. And since a virtue of this system is that it doesn’t block the main thread, relationship faulting would have to be carefully designed so that it’s async but still convenient for the developer. (Tall order, I know.)

Buuuuuuuuuuuuuuuuuut this is just me dreaming. Projecting my own preferences.

But still, if you were starting from scratch in 2014, designing a data layer for iOS and Mac, in the era of closures and GCD and Swift, in the era of CloudKit and web services, how might you do it differently?

Well. As I said, were I starting something new, I’d use Core Data, and happily. No question at this point. But part of me would keep wishing for a fresh start — a la Swift and CloudKit and Metal.

The thing is, these days, fresh starts seem possible. Two weeks ago it didn’t look that way. I have no inside knowledge, though, so getting your hopes up is not indicated. (And, anyway, it’s just me that’s hoping.)

Can iOS Developers Skip Learning Objective-C?

Aaron Hillegass says no — iOS developers need to know Objective-C. I agree.

Seattle Xcoders Thursday

There’s a meeting this Thursday at 7 pm at Omni. I’ll be doing a talk about Vesper syncing. I suspect that the talk may take a turn into a general discussion about CloudKit, Swift, and other WWDC announcements.

Afterwards we’ll go the Cyclops, as normal.

Vesper’s Custom Navbar

We don’t use a regular UINavigationBar with Vesper. (We don’t even use a UINavigationController.) What appears to be the navigation bar is a custom view that doesn’t descend from UINavigationBar.

The reason for that is that we have transition animations that I don’t know how to do using a UINavigationBar. Here’s a screenshot of the navbar as you’re swiping back from detail to timeline view.

Vesper navbar screenshot

Note that the < and + buttons are at full opacity and don’t move, while All Notes and the icons are in mid-fade. (And All Notes is moving from left to the middle of the navbar.)

The reason for this is that the leftmost and rightmost buttons appear in both timeline and detail view, and in those same locations, so it’s nice that they don’t animate at all.

My question: is there a way to accomplish this using a real UINavigationBar? I like custom UI and our design, but I’m much happier when the implementation can be based on the standard stuff.

I think I made the right call — the only call possible. But I’d love to be wrong.

JavaScript Theory

JavaScript is nobody’s first choice of language. (Almost nobody, maybe. There’s always a language you like better.)

But it’s everybody’s second choice of language — for the simple reason that everybody thinks that it’s everybody’s second choice of language.

(Maybe this is too clever to be true. Working on it.)

Temptation

Instead of diving right into Swift by writing Vesper for Mac, I’m tempted to do a warm-up project first, just to get the hang of the language.

Chris Lattner on Twitter:

Of course Swift supports #! scripts, you can immediately execute a swift script with "xcrun swift -i".

What’s the obvious thing to do? I could replace my Ruby-based static blog generator with Swift code.

I probably won’t do this. But I’m tempted — and I bet somebody does this.

JavaScript and Interapplication Scripting

See the JavaScript for Automation Release Notes.

This Mac scripter from the ’90s says that this is the long-promised programmer’s dialect of AppleScript. It’s much like UserTalk.

Vesper Mac Diary #1 - the Plan

The last Mac app I wrote was NetNewsWire Lite 4.0 for Macintosh, released in March 2011 — over three years ago.

Before last week, before WWDC, I would have said that the big changes to Mac development since 2011 were view-based table rows and the NSURLSession APIs. Which would have meant that I didn’t have a lot to learn to write a new Mac app.

Which is fine. With Vesper 1.0 I learned a ton about Core Text, custom UI, and transition animations. With Vesper 2.0 I learned JavaScript, Node.js, and how to write a syncing system. That’s a lot of learning in a year-and-a-half, and I deserve a break.

Well. I don’t want a break.

After WWDC 2014, Mac app development has changed substantially. There’s so much to learn.

The plan right now:

  • Write all new code in Swift.

  • Use storyboards.

  • Use auto layout.

  • Adopt the new appearance APIs (vibrancy and so on).

  • Do things I’m not thinking of because I’m still overwhelmed with even just listing what’s new.

There are some things I’m not going to do. I could rewrite existing code in Swift, but that would just be me spinning my wheels. Not worth it. And now that Core Data has fixed two of my big three wishes, I could switch — but that would be malpractice, since I already have a working, fast, and efficient model layer.

The plan could change. I do, after all, need to ship, and I can’t take a serious amount of extra time just because I want to learn all the new things.

But this is going to be fun.

Dave’s Design Diary

My co-worker Dave Wiskus is writing about designing Vesper for Mac:

I’m excited not because the work will be easy; Mac is still not my core strength, and this will likely be the hardest work I’ve ever done. What I’m excited about is that for the first time the three of us — Brent, John, and myself — are all speaking the same language on the Mac.

[Sponsor] Microsoft Azure Mobile Services

Microsoft Azure Mobile Services provides a scalable and secure backend that can be used to power apps on any platform — iOS, Android, Windows, or Mac.

With Mobile Services, it’s easy to store app data in the cloud, authenticate users, and send push notifications.

Built from the ground up to be flexible and extensible, Mobile Services lets you code your app backend in C# or Node.js. You can save app data either on-premises or in Azure SQL database, blob storage, table storage, and MongoDB.

Notes on CloudKit

I just watched the introduction and advanced sessions on CloudKit. I’ve recently written my own backend syncing system using Azure Mobile Services, and that’s the perspective I’ll bring to these notes.

(Disclaimer: Mobile Services is sponsoring this site this week. That’s not why I’m writing this, but I should say that up front.)

First off — holy shit.

It’s closer to the metal than, for instance, iCloud Core Data syncing. The backend is not tied to the local database layer. It handles blobs and structured data.

It differentiates between public and private data.

The APIs are a transport mechanism. It uses change tokens for delta updates (what I called sync tokens). There’s no magic, and error handling is necessary.

Authentication and identity is handled by the system, and privacy is emphasized.

In other words: it’s wonderful.

Limits

Could we have used it for Vesper, had it been available a year ago?

Almost. There are three things that would have prevented it, and the first two are huge.

It’s only iOS and OS X. I understand that that’s the point, and I don’t say that Apple’s wrong for doing it this way. I get it. But using CloudKit means not being able to do a Vesper web app, and we’re keeping that option open.

The second thing is that there’s no facility for building services on top of these services — there’s no way to run my own code in the cloud. I require that, because there are services I’d like to build. (How cool if it allowed us to run our own Swift code on the server.)

The third thing that would concern me about using it with Vesper is the limits. It’s possible those will change, and it’s possible that more clarification would take away those concerns.

Here are those limits. Some of them looks insanely generous — 1PB for assets storage!

But also notice that the data transfer grows just 0.5MB/user for assets, and 5KB/user for database. That’s not actually that much, and I could see going over those limits. And I know from experience that it’s difficult to estimate in advance what the average user’s needs would be.

What happens if we hit those limits? I don’t know. More information would be good. Actual experience by a number of developers who can share their stories and numbers will also be helpful.

I’ll put it this way: even if we could use CloudKit for web apps, and even if we could add our own code, I’d be concerned enough about the limits to want to talk to folks at Apple to get more information. My suspicion is that Vesper would have been fine, but I wouldn’t have allowed optimism, however reasonable, to prevent me from due diligence.

Resemblance to Mobile Services

I mentioned that we use Azure Mobile Services in Vesper. This system is similar in a few ways: there’s a framework that lets you upload and fetch and run NSPredicate-based queries; there’s a portal where you can configure a bunch of stuff; and it uses a just-in-time schema for the database.

At first I thought that structured data was stored in a NoSQL database, but instead it appears that it does what Mobile Services does. When the endpoint gets an object with properties, it dynamically updates the SQL database schema to include any previously-unseen properties.

Then, before you deploy, you freeze your schema.

I don’t think that CloudKit is built on Mobile Services, but it’s possible that it’s built on some of the same tech. That just-in-time schema seemed very Azure-like to me. (I know people. Everyone says they can’t confirm or deny, which is not a surprise, but we do believe that Apple has used Azure for other iCloud services.)

Resemblance to Azure Table Storage

At first I thought that structured data was stored in Azure Table (NoSQL) storage because of the references to zones. A zone in CloudKit could correspond to a table in Azure table storage or a container in Azure blob storage.

And it’s totally possible that structured data actually is stored in NoSQL table storage, and it just looks sort of like SQL because it enforces a schema eventually, but I doubt it.

Unstructured data, however, would have to be stored in Azure blob storage or something like Amazon S3. (It’s entirely possible that Apple uses multiple providers, of course.)

Summary

One of the slides said that syncing is hard. While this makes it much easier, it doesn’t do everything. You still have to handle errors and conflicts. It takes design and work.

But that’s to be expected.

And it’s nice. Real nice.

Could you write a traditional RSS reader with a content service with it? If you could figure out how to get your feed crawler to get content into the public database. If you can figure out an efficient way to store read/unread states of many thousands of items per user. So: maybe.

How about Glassboard? CloudKit has public and private data, but no groups, so this would take some trickery. If you could do it, it would be at the expense of bending some things, and it might not be secure. And then you’d have to kill the web and Android clients. So: no.

But I still bet that lots of apps will benefit from this. Somewhere people are thinking about their existing apps and how they’d benefit — and people are planning new apps that they wouldn’t have otherwise been willing to try.

I think this is going to be a huge deal. I think it’s the first time Apple has really nailed a web service for developers. And I tip my hat to the team (or teams) behind all this. Good job, folks.

The Core Data Team Is Screwing With My Head

I take it personally. I know that’s self-centered.

But look at what they’ve done:

  • Bulk updates — solving the RSS reader problem of needing to mark 10,000 items as read all at once.

  • Asynchronous fetches — solving the problem of blocking the main thread.

I don’t know what’s left for me to complain about. Good job, Core Data team.

(Apple folks can see rdar://15183235 and rdar://15183183. Which I’ve just marked as resolved.)

WWDC and Design

Dr. Drang: How it works:

Now, when I need to analyze a structure or a piece of equipment, I ask for the design drawings. In my world, design is what engineers do to make things work.

Our point of view at Q Branch is that engineering is part of design. So while it’s easy to say that I work with two designers, and everybody knows what I mean, the truth is that the company is made of three designers.

If Vesper Sync works well, is unobtrusive and fast and easy to set up, it’s because all three of us designed it that way.

Is Chris Lattner a designer? Hell yes. As are the zillions of great Apple engineers who don’t know Photoshop from MacPaint.

(I’ve been watching the videos. My head hurts in the best way possible.)

Developers

My co-worker Dave Wiskus writes, in Macworld: WWDC 2014: The developers take the stage:

As interesting as any piece of technology announced on Monday, Apple is subtly but intently acknowledging a simple truth: this stuff is pop culture now. We were shown the future of Mac OS X, the future of iOS, and the future of apps. Brace yourselves, developers: the real consumer product being showcased at WWDC 2014 was us.

Swift + Twitter

If you’re interested in Swift — and you ought to be — you should follow Chris Lattner on Twitter.

Early Thoughts on WWDC 2014

It was the best WWDC in the years I’ve been going. (Since 2003.) I didn’t actually have a ticket — due in part to not trying to get one — but I was there to speak at AltConf and see friends and make new friends.

We will think of this WWDC as the beginning of a new era at Apple. It’s not true that Apple just woke up one day as a changed company, but it’s a convenient and obvious marker.

I’m excited. Surprised — multiply surprised, surprised over and over — and happy.

I haven’t even watched any of the videos yet. (They’re downloading as I’m writing.) But of course I have a few thoughts already.

CloudKit

I joked in my talk at AltConf that I might go down as the last guy in history to write his own custom syncing system.

I have wanted Apple to partner with Azure to make web services and syncing easier. This seems like a step in that direction. (I don’t know if they’re using Azure, but my intuition thinks so. Apple has used Azure before.)

Could we use this for Vesper? Well, I’ll know better once I’ve watched the videos. But it appears that it can be used for iOS and Mac apps only, and it’s important to us that we leave open the possibility of a Vesper web app. (I’m not promising anything, of course — just explaining our thinking.)

There are also some data limits that might have precluded our using it for Vesper. I need to learn more about these.

But this is just an evaluation of CloudKit for our specific needs and not a general critique. John Siracusa calling it rational tells me it’s designed well. My guess — early as it is — is that this is going to get used in a ton of apps.

I don’t really think I’ll go down in history as the last guy to write his own syncing system. But I bet there are people right now who realize they don’t need to write that syncing system they thought they’d need. And I bet there are people right now planning apps that CloudKit makes possible and economical.

Swift

I keep calling it Self, but only because of the similarity of name. I’ll get over it.

It probably has some things in common with Self, but I know almost nothing about Self and couldn’t say. It has things in common with lots of languages, as it should. Of newer languages, Rust appears to have a decent amount of influence.

I’m lucky. I’ve just started a Mac app, and I plan to write it in Swift.

I’ve heard other developers say they want to wait about a year, and I totally understand that attitude. It’s reasonable to assume that Swift code written today may not compile in a few months — it’s a work in progress.

But my thinking is this: if I start using it now, I can provide feedback, and that feedback will help shape the programming language that I’m likely to use for the rest of my career. Maybe I’ll have a ton of feedback, and maybe I’ll have none — but I’d sure hate to have missed my chance to help.

I’m no language purist — quite the opposite. I’m a pragmatist with many years of experience who wants to write better software more quickly.

I did not expect Swift. I expected it in five years, maybe. But this is — far and away — the thing I’m most excited about. (I’m about a third of the way into the book.)

Playgrounds

I suspect that before long it will be hard to remember what development was like before Playgrounds.

Other Things

One of the jokes this week is that suddenly we developers have nothing left to complain about. It was all taken care of on one Monday in June 2014.

But we’ll find things, of course.

It was like this, though — we kept hearing about things, even relatively small things, that all by themselves would have made for a great week. It was like the greatest Christmas ever — and then Santa Claus hung out so you could take selfies with him. This friendly and generous Apple reminds me why I love writing iOS and Mac apps.

Okay. I’ve got some videos to watch.

River4 RSS Reader

Dave Winer has released a new RSS reader, River4. Node.js app. Up on GitHub.

[Sponsor] Microsoft Azure Mobile Services

Microsoft Azure Mobile Services provides a scalable and secure backend that can be used to power apps on any platform — iOS, Android, Windows, or Mac.

With Mobile Services, it’s easy to store app data in the cloud, authenticate users, and send push notifications.

Built from the ground up to be flexible and extensible, Mobile Services lets you code your app backend in C# or Node.js. You can save app data either on-premises or in Azure SQL database, blob storage, table storage, and MongoDB.

Archive