Sound Off Round 4: Live-Captioning Open Source & Feelings

From Sound Off: Open Source & Feelings has a thorough and unambiguous code of conduct, one of the best diversity statements we’ve seen from a conference, and an about page with everything from venue accessibility, to public transit, to tips about keeping safe while traveling to and from the conference. Everything about Open Source & Feelings communicates thoughtfulness, deliberateness, and listening to feedback. Donate now to help out this good cause. Sound Off board member Ashley Nelson-Hornstein explains how live-captioning is useful for all physically-present attendees, not just for people you’d expect to need the help. It’s also worth remembering that accessibility issues aren’t just something for a small percentage of the population. Everybody has — or will have, if they live long enough — something they need help with. I have increasing trouble hearing, and live-captioning would certainly help me, and maybe you too. Straight up: help make sure everyone can participate. PS The conference will be here in Seattle, at Seattle Central College. I was on the college newspaper there, in moons past.

Posted by on 14 July 2016 | 4:06 pm

My Rules for Mutable Foundation Collection Objects

I have some simple rules that I always follow when dealing with mutable Foundation collection objects (plus mutable strings) in my Objective-C code. Construction I often use a mutable collection object when constructing a thing — array, dictionary, set, or string — and then pass it somewhere else. Once it’s passed, ownership is relinquished. The construction code never continues to hold a reference to the thing it made. Wherever that thing goes it’s treated as immutable (whether or not it really is). No mutable collection objects in APIs In my .h files, under no circumstances are properties or parameters allowed to be mutable collection objects. (Or, well, it’s extremely rare. There could be a utility API that takes a mutable thing, but that API does some kind of work that doesn’t retain that collection, so it can’t mutate it later on.) Mutable collection objects are internal to a .m file An object may use mutable collection objects internally, but those aren’t allowed to escape the .m file they live in. There’s no chance, then, that one of these could be mutated without its owner knowing about it. * * * By following these rules — which, after all these years, I do without even having to think — I never run into an issue where I’ve passed a mutable array (or whatever) to another object, then held on that array and mutated it. It just can’t happen. But, really, whatever — these days I write Swift code instead.

Posted by on 30 June 2016 | 5:04 pm

Copy vs. Strong NSArray Properties

At work this morning I added a property to an Objective-C object that looked something like this: @property (nonatomic, strong) NSArray *someArray; And then it was suggested to me that copy would be better than strong in this case. I have nothing against copy — but with an immutable array, is that really necessary? The array can’t change, so why copy it? Well… that’s not strictly true. A caller could use an NSMutableArray — which would be perfectly valid — but then hold on that array and mutate it later on, which would be dumb. So I ask: who would write code like that? It’s not a class of mistake that I personally make. (I’ve internalized this so completely from years of writing Objective-C. I do make other classes of mistakes, of course.) And then I think “Who would write code like that?” is the wrong question. The real question is, “Why wouldn’t I write code that minimizes the effect of a possible mistake?” (Or even not a mistake. It could be entirely legitimate that the caller has a mutable array that it holds on to and mutates later on.) * * * This makes me wonder about the difference between code I write for myself and code I write as part of a team. Since I know that I wouldn’t make this particular mistake, I can safely use strong instead of copy in my own code. But, really — sharp right turn here; buckle up! — doesn’t it make me wish everything was already in Swift, so we’d have the safer behavior automatically? Yes. Yes it does. My personal projects are mostly in Swift — converted to Swift 3 already — but, for obvious reasons, at work we often write new code in Swift but still have a large Objective-C codebase. What I don’t need in life — because it adds complexity, and I don’t have time for that — is three separate coding styles: Swift, my Objective-C, and work Objective-C. The only one I can get rid of is “my Objective-C.” Okey-doke.

Posted by on 30 June 2016 | 4:07 pm

So Merlin Says to Me…

I saw Merlin Mann before the Talk Show last Tuesday, and he thanked me for letting him play in my internet treehouse. I completely misunderstood. He was talking about a small and specific thing (I realized later) — while I thought, at the time, he was doing a thing Merlin would do, which is to thank a software developer for helping to build up the world of blogs and podcasts where Merlin does, indeed, get to play (and be awesome at it). (What you don’t know about Merlin — or maybe you do — is that he’s one of the best at liking people. It’s creativity and Jonathan-Winters-meets-James-Joyce — but mainly effort and empathy. So he would say what I thought he said.) Anyway, my answer didn’t make any sense, surely, when I said, “We built it all for you.” (Because he’s thinking of this one small thing and I’m thinking of the web.) But it struck me that, as a reply to what I thought he said, it was absolutely correct. We — and I mean me and many thousands of people like me — worked hard to make the decentralized web, the web of blogs and podcasts, a place where all the Merlins would thrive. Blogs are the Pad Thai, the rib-eye steak, the bowls of spaghetti of the web. Podcasts are the mashed potatoes, the tacos, and the hummous. You could get by for a little while with Skittles (Twitter) and peanut butter cups (Facebook) — but eventually you need something more filling, something you can sit down with and take your time. * * * I realize that decentralized-web fanatics are often looked at as if we’re the Libertarians of the web. Or the crazy-conspiracy-theorist-uncles. Or as if we’re stuck, sadly, in a rosy past and we won’t move on. Think whatever you will. But wonder if, if all this goes away, could there be any more Merlins.

Posted by on 17 June 2016 | 6:10 pm

A Meaningful WWDC

Last year I was all set to go to WWDC — or, rather, to everything but the actual conference — with plane tickets and hotel rooms booked. I was going to speak at AltConf and play with the Breakpoints and hang out with old friends and make new ones. But, right before, my father-in-law died of complications from the treatment of a year-long illness. We thought he would get better, and then he didn’t. (This is what prompted my In the Room post of last October, even though that talked more about my grandfather.) I was very close to my father-in-law. He lived nearby, in the suburbs, and he was a big part of my life for 25 years. Naturally I canceled my trip. When he died, it was already clear that my mother-in-law was also sick — for entirely different reasons, and entirely coincidentally. So we went from one to the other without a break. I was as close to her as I was to him, and she died this past January. Both were too young, and both had been marvelously healthy and energetic — and I still keep forgetting that they’re not just traveling or something and I’ll see them soon, and then I remember. * * * So this WWDC represents something for me. I missed it last year, but this year I can go and have fun — and that’s a real thing. I’ll speak at AltConf, play with the Breakpoints, and hang out with old friends and make new ones. Same as last year would have been, but this year it’s different. Knowing that I missed it, but that I get to go this year, is helping me in a way it’s never had to help me before. It means something. And I thank everyone in advance just for literally being in SF at the same time as me next week.

Posted by on 10 June 2016 | 4:51 pm

Seeking Clarification

I have a side project, a Mac app, that I could also do as an iOS app. I have no plans to do so — but the news about subscriptions and free trials makes me reconsider. It might be sustainable with this new model. But here’s the thing: the app is a stand-alone thing. I’m not running a backend web service for it. Would it be okay to use the subscription-based pricing? Here’s what Apple says: Starting this fall, apps in all categories on the App Store will be eligible to offer in-app purchases for auto-renewable subscriptions to services or content. Users enjoy the reliability that comes with subscribing to a service that they love, and the experience must provide ongoing value worth the recurring payment for an auto-renewable subscription to make sense. Although all categories of apps will be eligible, this business model is not appropriate for every app. What does “not appropriate” mean? Does that mean rejection? Or is that just a warning that it’s maybe not the best fit, but it’s okay to try it anyway?

Posted by on 8 June 2016 | 2:22 pm

The Clean Screen Habit

I’ve spent years of my programming career on a team of one, and I ended up developing some idiosyncratic habits. One of them could be called the “clean screen” habit. Here’s the scoop: Xcode’s warnings and errors pane has to be clear at all times. If anything appears there, it has to be dealt with immediately. I enforce this in part by turning on treat-warnings-as-errors, so I’m forced to deal with everything. Also: anything that appears in the Console pane must be dealt with immediately — that is, any message must be some kind of assertion failure or notification that something bad has happened. Otherwise it must be kept clear (with the exception of temporary caveman debugging). Having these two panes clear tells me that the baseline health of the project is good. And it ensures that when something does appear, it’s an extraordinary event that I can’t miss — and can’t miss dealing with. * * * You could argue that this is pointless and fussy. After all, this doesn’t do anything to prove that the app is well-architected or that I’ve chosen good algorithms or that it uses memory efficiently. But that’s like saying showers are worthless because they don’t make you a snappy dresser. Cleanliness is just a start, but it’s a good and necessary start.

Posted by on 3 June 2016 | 2:27 pm

Oldie Praises the Old Old Ways

Swift’s support of inner functions is one of my favorite features of the language. Years ago, back in the ’90s, I used to write in UserTalk, the language that powered UserLand Frontier. It was a procedural scripting language — but remarkable for its integration with Frontier’s hierarchical, persistent database. (Storing a string in the database, for example, was just a matter of assigning to a location: = "baz".) In the early days of web programming, we’d often build a page just by appending to a string. In UserTalk it looked something like this: on buildPage()   local (htmlText)   on add(s)     htmlText = htmlText + s + "\n"   add("<html>")   add("<head>")   // …build the rest of the page…   add("</body></html>")   return htmlText The on add(s) bit was the inner function, and it could refer to variables in its enclosing scope. That’s a simple example, of course — we did more with this feature than just appending to strings, but it gets the idea across. Objective-C Before we get to Swift, let’s start where I started, with Objective-C. Some time last year I wrote a macro processor. The API looked something like this: @interface MacroProcessor : NSObject - (instancetype)initWithText:(NSString *)text values:(NSDictionary *)d; @property (nonatomic, readonly) NSString *processedText; @end That’s not an uncommon pattern. Initialize an object with some input, and then get the result (via the readonly processedText property). I’d call it like this: MacroProcessor *macroProcessor = [[MacroProcessor alloc] initWithText:text values:values]; NSString *processedText = macroProcessor.processedText; It sure just looks like a function call at that point, right? But weirdly split up into two lines. So I added a C function to the API to make this more explicit: TextWithMacrosProcessed(NSString *text, NSDictionary *values); Now I could call it like this, instead: NSString *processedText = TextWithMacrosProcessed(text, values); That C function just wrapped up the two lines (alloc-init MacroProcessor and return processedText). (I could have, alternately, made a class method on MacroProcessor. Either way’s fine.) Then I thought: well, I have the API I want — a function call — so there’s no need to make initWithText and processedText public, so I removed everything but that C function from the .h file. Great. Fine. That’s the beauty of interfaces, right? The important part is to get the API right. How it works under the hood (creating an object, etc.) is an implementation detail. I could have stopped there. But I didn’t stop there Let’s be clear: MacroProcessor had unit tests and zero known bugs. It had no side effects. It was good, solid code. A smart developer just moves on to work on something else. But, since this was part of a Ranchero project (not an Omni app) with no ship date and no hurry, I could allow myself some extra time. Even though I had the API right, it bothered me that the implementation didn’t feel quite right. After all, if the API is a function, wouldn’t it be ideal if the implementation was also a function? Is that even possible? I looked at the structure of MacroProcessor, and it was what you’d expect: three properties (initialText, values, and processedText) and a handful of methods. For some reason it flashed in my head how I’d do this in the old days, back when I was writing UserTalk. There’d be a function with some local variables, and some inner functions that did things, and it would return the final processed text. Like that buildPage example above. And it occurred to me that the structure is actually the same: some functions have access to variables that nobody else has access to. Whether that’s an object, or it’s a function with variables and inner functions, amounts to the same thing. So I approached it that way, and wrote it like I would have in the old days (only in Swift this time), and it worked perfectly. (Still has unit tests, zero known bugs, and no side effects.) And the API is now textWith​Macros​Processed​(text: String, values: [String: String]) -> String, and the entire thing is just that one function. No object needed. Good old days, bad old days So one day I talk about how I don’t want to write code like I did in the old days. And today I’m happy because I’m writing code like the old days. There’s no contradiction. Some stuff from the old days was awesome, and some was fine, and some was bad. Writing Swift this way to do something that I’d solve with an object in Objective-C — at least in the case where it really ought to be a pure function (takes input, does a thing, doesn’t look at or change anything else, returns output) — is great. Love it. (Pure functions make me unreasonably excited. I think I get this from my Mom.)

Posted by on 1 June 2016 | 3:56 pm

Wil, Chris, Waffle, Samuel, Soroush

Wil Shipley: So Cocoa programmers are in a tizzy A TIZZY I SAY at the prospect of going back to the bad old days (eg, 1987). And… I urge anyone who's speculating about Swift's possible future missteps to look hard at the team that's brought us LLVM, clang, ARC, and Swift, and think, “it’s pretty likely they’ll handle this,” not, “OH GOD EVERYTHING I LOVE IS ENDING.” (The latter of which, incidentally, is my nightly mantra.) The tizzy is part of the process. I like to think that the various blog posts and Twitter discussions are contributions to a discussion rather than just words expended for no reason. It’s not venting or declaring that the sky for sure will fall — it’s people doing their part to think and communicate about tools that are important to them. Also: 1987? For Wil, 1987 may have been the last of the bad old days. For other people, 1997 is more likely — but for me it was 2002, and for other people the bad old days are even more recent. Consider Elm. People have talked it up to me, and it looks pretty cool, and I’m sure it’s awesome in a bunch of ways, and there are probably a bunch of things to learn from it. But look at this small example of handling button presses. There are two buttons, and there’s a case (switch) statement to handle the message. In a small example like this it doesn’t seem onerous. But an app is a much bigger thing, and doing this kind of thing everywhere would work me into a tizzy. * * * Chris Eidhof: Yet, techniques you don’t know will almost always seem more complicated at first. I tried arguing with a Haskell programmer that runtime programming can be useful. I tried arguing with a Ruby programmer that static types can be helpful. To both, it seemed unnecessary and complicated. They’ve been writing great code without those features. * * * Waffle: What I also expect is there to be a dialogue right now about these kinds of details by people who know what they’re talking about, about how Swift could actually become more dynamic without copying the flaws of its progenitors and without selling out the feel, mechanics and (most of the) performance of the language. * * * Samuel Ford: My experience working with type strict frameworks is that they are fussy. It’s like if the only way you could chop things when cooking is with an array of specialty chopping tools that have to be assembled from pieces every time you needed them. And you have one for garlic, another for potatoes, and so on. Every time you start to cook, you’ll feel the weight of taking those tools out, assembling the pieces, then taking them back apart, washing them, and putting them away. What you’ll find over time is that the recipes themselves will adapt to require fewer chopping tools and will become more plain and more similar over time. * * * Soroush Khanlou: Primarily, the big thing I got wrong last year was that Swift is just plain fun. This weekend, I had the pleasure of helping a friend with code-review. His project is completely in Objective-C, and our code review session reminded me how rough the rough edges of that language are, especially after spending any time in Swift.

Posted by on 27 May 2016 | 12:44 pm

A Definition of Dynamic Programming in the Cocoa World

When I talk about dynamic programming on iOS and Mac, I mean this: An app can learn about its structure at runtime. An app can do things based on what it knows about its structure. An app can make changes to its structure. The first is things like knowing what methods an instance implements, or getting a reference to a protocol, class, or method from a string. (As in NSSelectorFromString and so on.) The second is things like being able to instantiate a class where the name wasn’t known at compile time, or to call a method or reference a property that wasn’t known at compile time. (As with performSelector:, KVC, the responder chain, and xib and storyboard loading.) The third is things like adding methods at runtime (a la Core Data) or adding classes — for instance, by loading compiled code from disk (plugins). (Note — because people sometimes misread what I write — this definition is not advocacy for a particular style of programming, nor is it a judgment of Swift, which, I repeat, I love, and is my preferred language. It’s to help us know what we’re talking about when we talk about dynamic programming.)

Posted by on 26 May 2016 | 3:19 pm

Oldie Complains About the Old Old Ways

I saw a thing on Twitter that said I’m just an old guy complaining about the new ways. Then the tweet was deleted, to the credit of its author. But let me take up the point. It’s not the new ways that bother me — it’s the old old ways. That is, how I wrote apps before I started using AppKit. In those days it was common to use C or C++ — always C for me, thankfully — and you may or may not have used an app framework (MacApp, PowerPlant, MFC, etc.). The app framework might generate code for you, which was a source of fragility and bugs. But, even if not, you had to do things like this: Menu item with unique ID is chosen App’s central event handler is called App looks at its context and dispatches event to the right function There were lots of switch statements. To add, for instance, a copy (or whatever) implementation to a particular view, you’d have to edit your event dispatcher to know about that particular view and its copy function. Making changes required making changes in various places. Sure, there were things you could to make this a bit easier. It didn’t have to be total spaghetti. But, even at best, it was bad code, and there was nothing you could do about it. Contrast that with the first time I used AppKit about 15 years ago. I wrote an action method in a view, wired it to a menu item in Interface Builder, and it worked. No switch statements, no touching a half-dozen locations just to add a command. I’m sure, that first time, that I didn’t even wire that menu item up to First Responder. It was wired directly. But, even still, AppKit used the runtime’s dynamic features to be able to find and call the right object and the right method. And that’s still true today. (Even in UIKit. Even if it’s a button. In other words, if you don’t think you’re taking advantage of Objective-C’s dynamic features, you totally are.) It seemed like magic, then. I later came to understand how it worked, and then it just seemed like brilliance. (Brilliance is better than magic, because you get to learn it.) * * * So when people like me write about these problems, it’s not because we fear the future and new ways of doing things. We love learning new ways of doing things — particularly when they’re better solutions to the problems we have. We’re not afraid of the future — we’re afraid of the past. We remember how these problems were solved by the static languages of the day, and we don’t want to go back. In the words of Guy English: If you see a switch statement or dispatch table they blew it. So, again, I’m documenting the problems currently solved by Objective-C’s dynamism, and suggesting that Swift, as it evolves, needs to take these problems into account. The foundation should be built with some idea of what the upper floors will look like. The answer doesn’t have to be that Swift is dynamic in the way Objective-C is, or even dynamic at all. But the eventual Swift app frameworks need to solve these problems as well as — hopefully better than — UIKit and AppKit do right now. And those solutions start with the language. PS I think I’ll write about plugins next.

Posted by on 25 May 2016 | 3:52 pm

WA Primary vs. Caucus

While 230,000+ people participated in Washington state’s Democratic caucus, 661,403 (and counting) participated in the non-binding Democratic primary. The results were even different — Sanders won the caucus by a large margin, while Clinton is winning the primary. Those results could be explained by several different factors, though, and that’s not my point. My point is that the caucus system decreases participation, and is therefore less democratic than primaries. In my state we have mail-in voting, which is more fair and accessible than caucuses or even going to the polls on election day. Anyone who works or cares for children or adults — or who has other responsibilities that keep them from participating in a caucus — can still vote via mail. And anyone for whom it’s physically or psychically difficult or impossible to attend a caucus has a much better chance of voting via mail. As a Democrat, it’s disheartening to see my own party effectively locking out many thousands of people from participating. This goes against my values — and it goes against the values of the Democratic party. (Or so I thought.) I wrote a note to the Washington State Democrats and argued the above. You can too. * * * The other thing people argue about is whether or not primaries should be open — that is, do you have to be a registered Democrat or Republican to be able to vote? I like Washington’s system: you have to check a box on your primary ballot that you consider yourself a Democrat or Republican. That’s it. I think it’s absolutely fair that a party would want members of its party to choose their nominee. You don’t want other people to choose your nominee for you. But at the same time it shouldn’t be onerous to declare that you’re a Democrat or Republican. If you’re not willing to do that much — well, then, that’s a valid choice, but you don’t get to vote.

Posted by on 25 May 2016 | 1:33 pm

Paul, Daniel, Dave

Paul Kim, On Dynamism: My problems aren’t performance. They aren’t type-safety (maybe it’s just me, but I rarely have issues with it and when I do, the time it takes to fix it is far less than the time specifying everything to a tee everywhere else). They aren’t being able to write clever VDLs. For me, it’s writing apps that solve my users’ problems and getting them out in a timely fashion. As it stands now, Swift (at least pure-Swift, or even current Swift as a non-ABI-stable moving target) does not do that for me. Now maybe these same problems can be solved in a static way but what I’m not seeing from the static-camp are (decent) solutions. What I’m seeing are either hand-waving or the same crufty code-generation, write tons of repetitive boilerplate type of solutions that I had hoped we had left behind in the 90s. What I do see makes me worry that it’s not the experienced app-writers that are being heard. * * * Daniel Jalkut, Not Perfected Here: Swift is a fascinating, beautiful language. How will it evolve to prove superior, in the long-run to Objective-C? By providing a suite of impedance-matched frameworks that fulfill all the needs of current iOS and Mac developers. * * * Dave DeLong posted 12 tweets on the subject, starting here, and including: 5/ but one of the things I love about @SwiftLang is that, since the dynamism isn’t there, I have to think about problems in new ways …and… 8/ I know that the people working on @SwiftLang are some of the most brilliant people in the world, and they all also love Objective-C …and… 10/ so maybe we’ll end up dynamism. Maybe we won’t. What we WILL end up with is one of the most kick-ass languages in the world Though I could ask about the frameworks (and I did), I can’t argue with Dave’s conclusion. I’ve said before, and will say again, that I’m writing all my new code in Swift and I’m enjoying it a ton, and I get bugged when I have to write Objective-C. In other words — if you think that the various people writing about Swift and dynamism are anti-Swift, you’ve got it wrong.

Posted by on 24 May 2016 | 7:40 pm

Dynamic Swift Comments on Hacker News

I don’t generally point to (or even read) comments on Hacker News — because in the past I’ve found that they’re like other comments on the web. However, I think the Hacker News comments on Michael Tsai’s Dynamic Swift post are worth reading.

Posted by on 23 May 2016 | 3:29 pm

Ash and Marcel

Ash Furrow, Adulterated Objective-C: …maybe it’s not important to re-invent Objective-C’s dynamic runtime in Swift. The language is far more static than Objective-C. And besides, a dynamic runtime is only a set of tools used to solve problems. In a different context, like Swift, different tools might be better suited. Problems currently solved with dynamic programming should have solutions just as good (if not better) in Swift and future Swift-only app frameworks. And “better” can’t mean, “Yes, it’s a big pain now and inelegant, but the compiler’s happy.” I’m skeptical that there is a solution short of adopting the same kinds of dynamic features Objective-C has, but I’m only skeptical. I don’t say it’s impossible. I want to be surprised and amazed. * * * Marcel Weiher, What's Missing in the Discussion about Dynamic Swift: The truly amazing thing about KVC, CoreData, bindings, HOM, NSUndoManager and so on is that none of them were known when Objective-C was designed, and none of them needed specific language/compiler support to implement. Instead, the language was and is sufficiently malleable that its users can think up these things and then go to implement them. So instead of being an afterthought, a legacy concern or a feature grudgingly and minimally implemented, the metasystem should be the primary focus of new language development. (And unsurprisingly, that's the case in Objective-Smalltalk).

Posted by on 21 May 2016 | 12:15 pm

Updating Local Objects with Server Objects

I’ve spent much of my career writing apps that store objects locally that come from the web — and that may change on the web, and then need to be updated locally. This kind of code can be tedious to write. Given a local object and an objectified version of some JSON or XML or whatever, I’d write something like this (translated to Swift for fun): if != { =   changeDictionary[fooKey] = } if != { =   changeDictionary[barKey] = } // multiply above a dozen times and for several different classes return changeDictionary Maybe you spotted the bug in the above, and maybe you didn’t — and that’s part of my point. I’d write this code using copy-and-paste, and then go over it visually, line-by-line, to make sure it’s right, and sometimes I’d miss something anyway. If foo and bar are both strings, for instance, the above would compile and all would be well. Except that I’ve written a bug where = Eventually I found a better way — some code that I can write once, and that can’t have the bug I wrote above. See this gist. * * * The solution is pretty simple. You have two objects — which may or may not be the same class but where the properties have the same names — and then loop through an array of mergeable property names. (The two objects don’t have to have the exact same list of property names. They just have to have the mergeable property names and types in common, since those are the ones we care about.) Then there’s a method that compares the local and server objects. For each property name in the list, it gets the localValue and serverValue using valueForKey:, and then compares them (via isEqual:). When they’re not equal, then it uses setValue:forKey: on localObject to give it the serverValue. It also adds the property name and new value to a change dictionary. (That dictionary could be useful for efficient database updating, sending notifications, etc.) There are places this could go wrong, and where the compiler wouldn’t complain. In the gist there’s this line: static let mergeablePropertyNames = ["dog", "cat", "zebra", "numberOfAnimals", "fedTheTigers", "attendingDoctors"] Obviously that line has to be maintained, and it has to be true that both local and server objects have those properties and those properties have to be of the same type. Yes. However, you’re going to notice any error at runtime pretty quickly, since you’ll get an exception — while you may not notice the = bug from the manual version any time soon. Best thing: you can reuse that updateLocalObject​WithServerObject method for all the various local/server object updating you need to do in all your apps. * * * Even though we’re writing in Swift here, the solution uses the Objective-C runtime and KVC. KVC is both awesome and to be used sparingly. Most of the time you want to write standard code that the compiler can better check — you want to write = true. Absolutely. But there are those occasional critical cases where KVC creates more reliable code that’s easier to maintain, debug, and reuse. This is one of those.

Posted by on 20 May 2016 | 3:43 pm

Layers Conference

In case you haven’t seen it mentioned already — Layers is a design conference in San Francisco taking place the same week as WWDC. It’s “like a party, but for learning,” and promises snacks, and people I respect tell me it’s wonderful. Be sure to scroll down and look at the list of presenters. It’s amazing.

Posted by on 20 May 2016 | 1:18 pm

Gus and Craig

Gus Mueller: Being able to write dynamic, responder chain-like code in Swift or Objective-C (or whatever) is extremely important to me. And if I had to give one reason why it would be this: Dynamic code is less code, and less code means fewer bugs and maintenance. Craig Hockenberry: The community around Swift’s evolution is amazing. The language is improving quickly and dramatically thanks to talented developers inside and outside of Apple. It’s a remarkable open source project. My concern is that there isn’t a corresponding discussion about the things we’re going to build with this new language. As you’ve just seen, frameworks are important, yet there is no uikit-evolution mailing list. There is an imbalance between the tool and the craft.

Posted by on 20 May 2016 | 1:01 pm

What I’m Doing With These Articles

In case it’s not clear: with recent and future articles I’m documenting problems that Mac and iOS developers solve using the dynamic features of the Objective-C runtime. My point isn’t to argue that Swift itself should have similar features — I think it should, but that’s not the point. The point is that these problems will need solving in a possible future world without the Objective-C runtime. These kinds of problems should be considered as that world is being designed. The answers don’t have to be the same answers as Objective-C — but they need to be good answers, better than (for instance) writing a script to generate some code. (Swift is just one part of that future world. The part I care about more, far more — as much as I love Swift — is any app frameworks built on Swift. But the design of Swift has an impact on the design of those frameworks.) There’s a second point: many people writing in Swift right now seem not to realize the extent of their reliance on Objective-C’s dynamism. Even if you don’t write a line of Objective-C, you’re running a ton of code that is Objective-C, and that dynamic runtime, and the app frameworks built on top, is what makes your apps actually work. This is kind of a “duh” thing, I realize, but it’s worth the reminder. Next up (probably Thursday or Friday) will be a thing on easily updating local model objects with data downloaded from a server. And then more to come.

Posted by on 18 May 2016 | 9:22 pm

0.0001% of the Way to Core Data

This post isn’t about Core Data — but it’s a well-known example of adding methods at runtime, so I’ll use it. Let’s imagine you want to make something like Core Data. You have a bunch of different model objects backed by a database. You want to implement faulting — that is, an object’s properties are nil in memory until you actually access one of the properties, at which point it pulls its values from the database. You have some options for how to do this. You could skip properties entirely and override valueForKey: and setValue:forKey:, and always access the values that way. Your overridden versions of those two methods would handle faulting. But this makes for a bunch of strings in your code, and it isn’t nearly as readable as = bar. Alternately you could create all the getters and setters by hand, for all the properties in all your data objects, and be sure to include a hypothetical fetchIfNeeded call in every single getter and setter. That’s a ton of copy-and-pasting. It gets you = bar syntax, but it’s also tedious, error-prone, and painful to maintain. (You could use macros or a script to make this a bit easier, but it’s still sucky.) Instead, you want to solve the problem reliably and once. You want maintenance of your data objects to be no more difficult than adding and removing properties and their associated @dynamic declarations. (Actual database schema maintenance is a separate consideration — that’s in the remaining 99.9999% of the way to Core Data.) While I can’t say for sure how Core Data adds methods at runtime, I can say for sure that this particular magic is available to us and not just to Apple. Which is as it should be — we have every right to expect that same power. How to add methods at runtime Here’s the plan. We’ll create a DataObject class that adds methods. Your model classes will inherit from DataObject. Your model classes will be free of anything odd — all that stuff goes into DataObject, which you can write once and then forget. You need a class method — + (BOOL)resolveInstanceMethod:(SEL)selector — that will get called when the runtime is looking for the accessors for your properties. If the selector is a getter or setter for one of your properties, then your resolveInstanceMethod will call class_addMethod, which appears in objc/runtime.h, with the appropriate parameters, including a C function that is the actual implementation of the method (an IMP). Example: class_addMethod(​[self class], selector, (IMP)getterIMP, "@@:"); It’s actually unbelievably easy. See my sample demo app on Bitbucket, which shows the basics. (You can get fancier than I did — you might start by using reflection to get the list of property names instead of using an array, for instance. You could handle non-object types.) But why? Maybe you’re thinking, “Great, but I already just use Core Data and don’t need this at all.” First: congratulations on using Core Data. It’s the right move. Second: imagine a different scenario — think of DB5. DB5 lets you put a bunch of appearance definitions — strings, colors, edge insets, and so on — inside a plist so that you don’t have to scatter all these values throughout your app. It’s a nice utility, but its API is all string-based, which means plenty of room for typos and errors. Imagine, instead, if you could define the set of appearance properties your app needs. This would make errors less likely: the compiler would be your friend. But you definitely don’t want to go through the error-prone work of actually creating a hundred accessors — you want those created automatically for you at runtime. As you might imagine, someone’s actually already done that: it’s how Omni’s OAAppearance class works. And, as a bonus, there’s an Xcoders talk from Curt Clifton that goes into detail. (The audio isn’t great, but the talk is worth it anyway.) And, as a double-bonus, OAAppearance is open source on GitHub.

Posted by on 18 May 2016 | 3:20 pm