Innocent Arrow Diagrams

Teaser image

Sketches and diagrams with arrows look very innocent, yet they mean so much for our work. But they only carry meaning if you’re honest with yourself and depict what’s really going on in the app; then they become a great tool to understand and analyze code. (Better than note-taking can ever be when it comes to object-oriented code.)

Continue reading …

It’s the Worst Time to Go Open Source Because So Many Stupid People Will See It

Junior Bontognali summed up what most people think about most other people – especially after the U.S. presidential election and Dash for iOS going Open Source: people in general are not ready for generous behavior.

Bogdan’s Dash for iOS is on GitHub now. One tweet highlighting an ugly if statement got lots of attention. One twitter user suggested cutting off Bogdan’s fingers. That’s not a real threat, of course. It’s just a stupid joke. But suddenly you’re in 4th grade again and everyone is making stupid jokes because someone pulled down someone else’s pants.

The thing is, Bogdan of Kapeli is too busy to accept pull requests that don’t add features. Maybe because testing these for regressions is pretty time consuming without and end-user benefit. Who knows. So he already turned down a pull request that would fix the aforementioned if-statement – and many others.

Dash probably isn’t ready for Open Source, either. A Swift library as simple as ReSwift took us over a month to port to Swift 3. Maintenance is time-consuming, no matter how big or small the project. Complaining is stupid and childish, but that’s the noise we have to deal with if we don’t want to be stupid and childish ourselves.

I don’t think everyone’s grown-up enough for democracy. I only hear about 3rd wave feminism and presidential elections in the U.S. from YouTube. Junior quoted Evelyn Beatrice Hall, and that applies just nicely to all the hate that’s going ‘round:

I disapprove of what you say, but I will defend to the death your right to say it.

It seems lots of people with the power to act in public space don’t want to defend anything except their own self-loathing and self-interest. (Looking at you, “safe space” discussions.) If you read my previous ramblings about morals, you will notice that I usually point out that bitching doesn’t help. It will only strengthen victim mentality. Only doing will improve the situation. That’s why I won’t stop open-sourcing code and I’m looking forward to getting feedback by amazing people. The majority of not-so-amazing people on the internet have to be filtered out. It’s worth the effort to reach the good folks.

Open Source and the Open, Distributed Mindset

We developers are familiar with the benefits of Open Source-distributed code: we can re-use the stuff other people achieved in our own applications and experiments. Giving back to “the community” feels nice, too. Most of the day-to-day benefits are centered around the free re-use. But the mentality of being part of Open Source is far more than that. I realized how precious the mindset is to me when I thought about how the gym I train at is managed.

Continue reading …

Dan Counsell’s Mac App Store Wish List

These wishes by Dan I can easily get behind:

  1. Eliminate or relax the sandboxing guidelines
  2. Revamped pricing models
  3. Emphasize quality over quantity
  4. Get rid of in-app purchases
  5. Streamline the approval process

The picture Dan is painting is dim, but it’s also spot-on. Wishes don’t always come true, and you probably know that some people on the web simply complain and write open letters to Apple instead of wishing for a better future.

Dan’s stance is more productive than complaints, though: Because when you complain, you’re adopting the mentality of a deserving victim. Change the status quo instead.

It’s your turn to do what’s right: if you don’t believe in what’s going on, make something better. On the Mac, you have the power to do so. As an indie app developer, you can distribute your software outside the Mac App Store. Or you can try new business models like Setapp is doing (which I presume to be subscription based for unlimited access to a wide range of apps).

Bitching doesn’t help. It doesn’t improve your own mental state, and it doesn’t make the world a better place. Only doing something will bring change.

Drawing from Dan’s list of wishes, a controversial topic is In-App Purchases. Some people say IAP are the future of making business, that paid up front is dead, and that developers should deal with the reality and adapt. Instead of finding out the truth, think about what you want to make, and which future you want to help bring about. Then act accordingly and never falter.

RocketData is a Uni-Directional UI Component Data Source

I watched “Managing Consistency of Immutable Models” by Peter Livesey where Peter shows how RocketData works. Very worth the time! I’d call RocketData a uni-directional data source. It’s uni-directional because you set up the DataProvider as the source once, wire update notifications to view updates via the delegate property, and you’re done with the setup. Update events include:

Continue reading …

Debugging NSBeep Error Sound in NSResponder Method Calls

I utilize NSResponder actions in TableFlip to move the selection around. Naturally, neither a standard NSTableView nor a custom NSResponder implement default behavior for (most of) the methods I need to support arrow key movement, tab movement, and the usual shortcuts, like Cmd-Left to jump to the first cell in the current row. Or Alt + arrow keys to insert a row or column next to the selection. So I implemented this in a custom NSResponder subclass.

Continue reading …

BundleHunt Experiment

I participate in this year’s BundleHunt “Holiday Bundle” (running until January). I submitted both the Word Counter and TableFlip – mostly to see what happens.

The Bundle Experiment

I’ll disclose the details of my calculation later. This is an experiment: does presence in a bundle with so many hundreds of thousands of subscribers affect my regular sales and visibility? Being part of the bundle is like advertising, only I don’t really pay anything, I just make a lot less money when somebody buys the app from the bundle ($0.60 per license sold, or 97% discount for an app priced at $19.99). If the bundle sells 5000 times and 50% of bundles include one of my apps, that’s about $47,000 I will thus have “spent” on marketing. Imagine that. What a crazy number!

“These 2500 people could’ve paid you $20 instead and you’d be rich!” – Not quite.

My tools are targeted at users with very specific needs. The bundle is mostly targeted at folks wanting to make a deal. It’s people I may usually not attract at all. So even if I sell 2500 licenses through the bundle, I bet most of the customers will be people who wouldn’t have bought the apps without the bundle. I don’t really lose money if that’s true.

Part of the experiment is to find out what kind of people are going to buy the bundle.

Bundle Customer Ethics

I said this sometime in the past already: if you care about 1 app in a bundle of 10 and don’t want or need the other 9, contact the developer directly and ask for a discount. If MyDreamApp costs $50 and is part of a bundle for $20, ask the developer to buy the app directly for $20. This way they will make 10x more than from the bundle alone (ignoring bundle fees). That’s infinitely more % than not having you as a customer at all. It’s a good deal for everybody.

If you really do want to buy the BundleHunt Holiday Bundle because of the great offer, use this link and I’ll get $5 extra as an affiliate. Merci beaucoup!

Exploring Mac App Development Strategies” 4th Extended Edition Now Available

Teaser image

I’ve just finished updating the book “Exploring Mac App Development Strategies” for Swift 3. Looking at my Word Counter, this 4th edition sports about 15000 new words in the book and code combined: I re-wrote a lot of chapters and source files. I also expanded a few sections to add more context and incorporate things I learned in the past 2 years.

Continue reading …

Resolving NSTreeController’s “Ambiguous use of ‘children’” in Swift 3

I’m converting code for my first book to Swift 3. It uses Cocoa Bindings a lot, including NSTreeController. Now the compiler changed; and one of the issues I faced was working with the NSTreeController.arrangedObjects. The compiler assumed a wrong type of the children property (see the docs) and reported “Ambiguous use of ‘children’”.

Continue reading …

Let Them Perish

Last week, Red Queen Coder’s blog post about iOS job interviews was discussed a lot. The interviewers asked her to sketch how to implement a linked list on a whiteboard. She couldn’t. And thinks it is pointless. (I agree.) But then people on social media responded that she should just learn (that is: memorize) that kind of stuff to get a good job. Read her transcript, it’s a well-written story of how a job interview and the onslaught by narrow-minded people who defend the status quo (and their own status as the establishment) made her wonder what’s wrong with the community at large.

Continue reading …

Clean Swift aka VIP Architectural Approach

The folks at Swifting.io wrote a blog post about iOS software architectures. The comparison of VIPER and Clean Swift/VIP is very interesting: the VIP approach favors uni-directional flow, which I like very much. The article is worth a read for that alone!

They falsely consider MVC and MVVM to be software architecture approaches, though, and too point out that MVVM and MVC suffer from similar drawbacks.

My Declarative Breakthrough: Wherein I Stop Thinking in Terms of Object Collaboration

I just grokked how value transformations can not be a pain in tests. I’m writing a simple export module which takes a table from TableFlip and renders it as LaTeX. So the input is a Table and the output a String. But the module is not just a single function, mind you. That’d be a huge function, and not very open for configuration changes later. I factored it into a few sub-components, of course.

Continue reading …

How to Refactor Messy Apps for a New Architecture?

When facing a legacy code base, changing the mess to an orderly architecture can cause confusion: where to start? What to do? An exemplary question: How do I refactor a Big Ball of Mud into layered architecture? Refactoring the existing code base seems like a logical step; after all, refactorings are designed to improve existing code, and improvement is what you’re up to.

Continue reading …

MVVM’s Place in Your App

Picking up on my post MVVM Is Quite Okay at What It Is Supposed to Do”, here’s a few images which illustrate the problem of mistaking MVVM for a solution to a structural problem. It’s the whole post in 2 images. Model–View–View-Model helps with the view layer. It can be a tool to break up a view controller into smaller things. But it’s still only a refactoring of view components into more objects.

Continue reading …

Developer Documentation App Dash Removed from App Store – and No-One Can Do a Thing

Dash was removed from the macOS and iOS App Stores: Apple terminated the developer’s account without further notice and does not provide additional information.

This is a very sad thing to happen to Bogdan Popescu, sole developer of Dash: as far as I can tell, Dash is the only app he is selling at the moment, and now the exclusive iOS store was taken from him. The macOS App Store was probably more lucrative for Bogdan than selling licences on his own – at least that’s what other developers consistently report when they sell on both platforms.

So here’s another reason why Apple’s App Stores are risky for developers. Not only will search ads skew the results. And not only do you have to make up for the 30% cut by Apple. Developers have no way to defend themselves against giants like Apple (or Amazon in the realm of books, for that matter). There’s no separation of powers. The companies own these channels. It feels weird that they can do as they please, but there’s nothing to complain, really.

The power of the customer is limited, too. Do you know anybody who doesn’t have a strong opinion why his smartphone is better than someone else’s? Anybody who would switch platforms at will? Who won’t lose anything in the process or find it painful? – I don’t, and so there’s no real pressure for Apple in the long run. Not paying for the next iPhone and using Android instead is not an option for most iPhone users. It’s probably even worse with Macs. I wouldn’t want to use a Windows or a Linux PC if I can help it.

TableFlip Launches

Teaser image

I pushed the button. Now TableFlip is here! TableFlip is a text-based visual table editor. It will become your go-to application to edit tabular data because it’s blazingly fast, lightweight, and fun to use. You can use it to quickly create tables from scratch and copy the result anywhere – or you can use it to edit tables in existing documents. That’s what “flipping” stands for:

Continue reading …

Apple Introduces Search Ads

So now you can place ads for your app to pop up in search results.

I don’t like this move. Because it changes the chances of developers to make it in the list of search results. The App Store’s aren’t a great place to discover a fitting solution. Now, the search results aren’t even guaranteed to be 100% relevant.

If I had the money, I’d use Search Ads to try to increase my revenue. Without money, you’re screwed, though.

At least the pricing sounds good: you pay for a tap and you can put a daily cap on your ad budget. So literally everyone can try to use Search Ads to increase the odds. The thing is that each tap is priced according to the market, though. If your competitors are willing to spend a lot more than you, chances are a limited budget will not make it:

You determine the maximum amount you are willing to pay for a tap on your ad. Using a second price auction, Search Ads calculates the actual cost of a tap based on what your nearest competitor is willing to pay for a tap on their ad, up to your maximum cost-per-tap bid, so you’ll always pay a fair market price. (Source)

Apart from the amount of fairness of pricing and other technical details, I find the very move to place Search Ads in the App Stores troubling in itself.

Swift 2.3 NSLocale UIKit API Changes Break iOS 8 Compatibility

We’re converting a rather big and clumsy project to Swift 2.3 at the moment. Strangely, NSLocale gives us a lot of headaches. The API hasn’t changed visibly, but the implementation seems to have. From Objective-C’s point of view: And from Swift’s: That property certainly isn’t new. Neither are the dozen others in that header file from Foundation.

Continue reading …

On Proprietarity of File Formats

The latin root of “proprietary” indicates this is something someone created in a special way. We can say it is owned by someone, intellectually. But then again, every file format was conceived by a human being; so the origin alone doesn’t suffice to grasp this concept. Take a look at the general introduction of “Proprietary format” on Wikipedia. Accessed today (2016-09-18), it reads (highlighting mine):

Continue reading …

Comment On “Real World Flux Architecture on iOS

The Flux architecture Benjamin Encz describes for the PlanGrid iOS app is like ReSwift only on a per-component basis: the user interactions fire change events that a store takes care of to mutate its state. The state then becomes the input for the view again.

It’s much like MVVM, whereas here the view model is the store’s state.

This Flux-like approach is still a big improvement over convoluted view controllers or not thinking about data flow at all. But I wonder if the gain is so much higher compared to properly separated MVC. Who reads the store’s state? Only the views? Then the state is truly a view model; but how do side-effect populate to the rest of the app, like renaming or deleting things? I’d tend towards dispatching the change event to other stores, too, which may or may not react to the event. Then the view component’s state is updated independently from the database, say, using the same event dispatch mechanism.

To model the flow of truth on a component basis (which is still uni-directional: from store to view) compared to a single global app state (ReSwift) sounds like a very easy to do component redesign. You can start with anything and “fluxify” it. Then move on to the next component that’s particularly convoluted. You may not even want to convert all your components to this data flow approach when some components are simple enough as they are. Symmetry of component design will suffer, of course, but if you’re aware of this and conclude it’s better not to convert everything, that’s fine.


With ReSwift, I interpret the global app state to be a state with real (Domain) Model objects. To make a state displayable, I derive view models from it. This came very natural to me. But Ben’s posts got me thinking: could there be situations where keeping view model state around is better than keeping “real” model state?

TableFlip Will Be Released in October!

Teaser image

It is time to go public: I’ll release TableFlip in October. Sign up for the release notification: http://tableflipapp.com/ Much love goes out to my beta testers! ❤️ You are great! I didn’t anticipate that we’d have so many discussions. Thanks for all your amazing feedback so far. The past 12 weeks were wild; now it’s time to calm down a bit and make things right.

Continue reading …

Tests Are Just Code, Too

From “Testing, for people who hate testing”:

The thing is, tests are just code. If you have a hard time constructing your own objects with some particular state, it might be a sign that your API is hard to use!

This is all there is to the magic of test-driven development, we could say. A test is client code. This means it doesn’t have the inside perspective of the object or module under test. It has an outside perspective. Through tests you see how your production code is used (by other parts of your code or by other people in the case of libraries, say).

You start with a test. This means: you start with an outside perspective, asking yourself questions like “What would be a good (public) interface for this?” – The opposite is ad hoc reasoning, something along the lines of “I have this NetworkManager there and maybe just call it and return the JSON. Okay. Oh, now JSON doesn’t work, I need to send a custom object along, so I’ll just parse the JSON and create an object. But if that fails, hmm, I cannot send nil, so I’ll force unwrap and let someone else deal with this.” Or something.
These improvised solutions can cause trouble because all they do is focus on the perceived requirements of the object you’re writing, ignoring the requirements of code that uses the resulting code.

Writing tests first kind of equals writing your app outside-in, starting with the calling code, then implementing the code that’s to be called. Only test cases are super focused and you verify a lot more behavior and setup code with a single run than you could ever do with manual testing.

Experienced programmers will be able to switch perspectives even without writing tests. Their experience helps them to make it less likely to produce waste, whereas “waste” is code you write and then discard because you find it doesn’t fit.

Programmer, Interrupted

Okay, interruptions kill productivity. Another recent article mentions planned interruptions to make things even worse. They talk about meeting appointments, for example.

But I dare say: interruptions are only ruining your day if they are external. If you take a break, things don’t look that bad. You can train yourself to re-focus. And I argue this is a useful skill.

It took me a while to train this skill, but nowadays I’m interrupting myself at my home desk every 30 minutes, get up and move a bit to stay healthy. I don’t need 10 minutes to refocus. I sit down, take a deep breath, and continue to write code. Just like that.

Heck, I even wrote an annoying break timer to force me to get up.

Talking makes things worse, though; makes it harder to re-focus. That’s pretty obvious, isn’t it? After all, you switch contexts and engage in a different activity that uses a lot of your attention. Socializing is important to us pack animals, so there’s no way to not read faces and listen for subtleties in intonation. It’s just what we do. And it pulls all of our attention away from other things.

If I have the work break for myself, though, I can continue to mull over a problem in my head. In this case, getting up and leaving the keyboard means to interrupt an activity that may not lead anywhere at the moment. I bet you know this situation: you can’t seem to figure out how to fix a bug because some components are too entangled; whenever you try to change something, something else breaks. (Of course this never happens in your own projects.) A break then interrupts the need to type on the keyboard and produce code. It helps switch from typing mode to thinking mode. It’s like facilitating the proverbial ideas you always seem to get in the shower.

If you’re afraid of interruptions eating away your productivity, I challenge you to install controlled breaks every 30 minutes to get used to the flow. Sitting for an hour straight already kills your body. You won’t notice if you’re not reasonably healthy; it just feels normal, but it isn’t normal.

I bet that my training to do regular work breaks makes me more resilient to short external interruptions. Put me in an office and see for yourself 😀

Assertions in Swift Kill Your Code

Swift.assert bit me, and it bit pretty hard. What do you expect to happen in this code: … compared to this code: If your answer is “only the second variant will actually execute sendAction in release builds,” then you’re way smarter than I. Until now I assumed that Swift.assert behaves similar to assertion macros in Objective-C where the code is passed through in release builds. I never cared to read the documentation:

Continue reading …

Switch VS Checkbox in User Interface Design

Teaser image
switch and checkbox

On the Mac, toggle or switch widgets aren’t very common, yet. On iOS, you don’t see lots of checkboxes. This article on UX Movement points out that switches are for immediate actions while changes to checkboxes require a submit button to be pressed.

Now I think about preference panes in Mac apps. They usually perform changes to NSUserDefaults immediately. But using switches on a Mac still feels wrong. Maybe just because I’m not used to it, but still.

macOS’s Notification Center has a switch to toggle “Do not Disturb”. It works, but I don’t use it a lot, so there’s not much opportunity to get accustomed to it.

When You Code, You Design Both Structure and Information Flow

As soon as you write a piece of software, you “architect” it. Can’t get around that; but if you do not do it consciously, the resulting structure may not be great. Taking ownership of the process is important to change the result and create maintainable software. When we write/architect software, we worry about two things:

Continue reading …

Transparent NSTableView Headers

Teaser image

An NSTableView is usually embedded in a NSScrollView. If you set the columns not to span the full width, the two of them will take care of drawing an empty table header cell to the right so that the interface doesn’t look weird. But I want to have a weird interface. Because TableFlip’s tables are different than the usual NTableView use cases.

Continue reading …

NSDocument Weirdness: Sheet Contents Appear Disabled

When I added a sheet to display on top of TableFlips’ document, I wondered why the text field appear disabled, tabbing through elements didn’t work, and overall functionality was limited to accepting click events: It turned out you have to make sure that you disable most of the NSWindow settings in Interface Builder except the title bar (NSTitledWindowMask). Only with a title bar (which is never visible in a sheet anyway) will the interaction work properly.

Continue reading …

Ownership of the Apps You Use: Ulysses App Pricing, Subscription Models, and the Death of Licenses?

It started innocently enough, with a customer being confused about paying for “the same app” twice. Now I wonder if the traditional pricing strategy for software is obsolete. I found this on Twitter, and then I got hooked: @fehnman @ulyssesapp like I said, it’s how you choose to sell it. +£50 for an app is pushing it.
—@eatmorefish (9:35 AM - 31 Jul 2016)

Continue reading …

On Reaching Mastery

The following isn’t a universal truth. It’s a report about my observations of a recurring theme in everything that’s great. First you imitate. Then you improvise. And then you may innovate. Imitation means repeating existing things to reach a deeper understanding of how it was done in the past. Improvisation means connecting the static patterns in creative ways to solve problems. Innovation means deviating from the known patterns in new and effective ways.

Continue reading …

Implementing CollectionType in Swift 2.x

I ran into trouble with custom collections the other day and wondered how to reliably find out what the bare minimum for a custom CollectionType is. The compiler will only help a bit: It’s conforming to neither CollectionType nor SequenceType. Now I know SequenceType requires the generate() method – but don’t let this fool you. CollectionType will provide that for you if you meet its requirements.

Continue reading …

Revamped Blog Archive

I just changed the blog archive to show all past articles reduced to the titles on one page. There still are annual collections of the old-style excerpts. I hope it helps to browse the stuff I published over the years. Still I find the sheer mass of topics unwieldly. That’s why I started to work on a curated and commented list of articles, like a table of contents. Will let you know when it’s ready.

Continue reading …

Splitting the View Models of TableFlip, a Short Aftermath

Teaser image

I executed my plan from earlier this week to split TableFlip’s monolithic view model into sub-view models. The process wasn’t too complicated. The highlights: The current hierarchy of controllers in the view layer is as follows: The window doesn’t look too complicated and there truly are not that many view components involved, but still it’s quite some work to keep things well coordinated. The TableViewController file clocks in at about 400 lines of code although it mostly delegates stuff to other objects. There’s still room for improvement, but I have to see patterns, first. I even extracted NSTableViewaDataSource and NSTableViewDelegate into different objects months ago. Today I doubt this was a good idea in the first place. We’ll see.

Continue reading …

I’ll Split Up the Monolithic View Model in TableFlip. Here’s What I Expect to Happen

The upcoming changes in TableFlip’s user experience made me ponder how I structured the app’s modules. The bottleneck I created in my app is simple: there’s one presenter which transforms the model into a view model; the presenter defines a protocol for the view it expects and passes the view model to the object that satisfies this contract.

Continue reading …

How PlanGrid uses a Flux-Inspired Architecture to Simplify State Management

Benjamin Encz published an article about the architecture of PlanGrid.

They moved to a Flux-inspired “unidirectional flow” approach where state changes are performed in a Store (in the backend, if you will) and updates pushed to the user interface (the frontend). No ad-hoc view updates, no shortcuts. User events are emitted, handled by the store, and state updates affect the view. That’s it. So it’s always obvious how the user interface got into the state it’s in: all the details are plainly visible in the current state object.

Ben’s post is very deep and detailed. You’ll learn a ton from it:

  • architectural discussion: why “unidirection flow”, and why Flux?
  • setup of actions/events and the store type
  • basic state–view bindings via Reactive Cocoa
  • how testing stores (and views) is straightforward with this setup

I can’t wait for the next post in this series. Most of this easily applies to ReSwift, too, of course. And guess who just got inspired to refactor TableFlip so the model and view become even more loosely coupled?

Iteratively Improving Your App: Decoupling Components at Module Seams and Adding Facades

Teaser image

Façades are very important tools when I flesh-out the modules of an application. They turn out to be only the logical consequence of basic object-oriented programming principles, internal cohesion of objects namely, paired with decoupling of application modules (like “model” and “view”). Take a complex view that has many subviews. When you need to update a single piece of the user interface, how do you get there?

Continue reading …

First Contact with AppKit for iOS Developers (Under the Radar #26)

During my rather relaxed late evening workouts I catch up on podcasts now. Although I don’t enjoy listening to people talk (I prefer reading), this is a great source of inspiration and seems to be the premier way in which people share their experience.

Marco Arment and David Smith run Under the Radar. In episode 26, they talk about Marco’s deviations into AppKit—Mac app development. (Their shows are always under 30 minutes, so I suggest you give it a try.)

Marco’s app Quitter is available for free. He couldn’t put it into the Mac App Store because its main feature is to quit other apps. That doesn’t work with Sandboxing. So Marco had to release it directly.

I found a few things especially noteworthy:

  • Direct distribution means you have to worry about installation, updates, and payments yourself. It’s more work. So Marco made it free. (P.S.: I wrote a book on direct distribution.)
  • Marco was rather afraid to ship an update: maybe he didn’t test thoroughly and introduced a bug; it seemed to me he missed the safety net of app reviews.
  • Then again, shipping a bug fix update is fast and easy, too. It takes zero time to make an update available to customers.

The absence of app reviews in direct distribution is both frightening and liberating. I am afraid to ruin my customers’s lives with every Word Counter update I ship. It’s true, you can break things. But you can also make things right within the hour. You don’t have to wait for anybody else. (Even though iOS app review times have improved a ton, from 7 to 2 days!)

I am astonished that both Marco and David have years of experience working with UIKit but didn’t ship a single Mac app in the meantime. Or do contract work back in the day. “iOS exclusive” sounds insane to me, but for them it has worked quite well!

What’s your experience? Do you remember your first contact with AppKit? Are you afraid to try? Comment, email, or tweet me your response!

I love Swift’s Expressiveness

Take optionals, for example. Optionals demarcate when something’s not there at all. When an optional is nil, this may signify something went wrong. That’s much more explicit than relying on a convention like returning -1 for failed requests. This is convenient and changes the game of handling edge cases completely. Because whenever you receive an optional, you have to deal with its two-fold nature. Checking for -1 can slip your mind. Forgetting to unwrap an optional is unlikely.

Continue reading …

UIStackView For Showing And Hiding User Interface Controls

Animating and (de)activating Auto Layout constraints always leaves me puzzled at first. When on iOS, I try to not add constraints with explicit width/height values to train myself to rely on relative values. This helps me cover multiple screen sizes with the same settings.

I asked Lawrence MacFadyen on Twitter recently if his UIStackView animation wouldn’t work without an explicit width. Seems it does, so he published an updated post.

Conflicting Mental Models in TableFlip’s Interface Design

A beta tester of TableFlip suggested I make the table grow automatically when one navigates to the edge of the table and presses the arrow key in direction of the edge. I am conflicted about this proposal. On one hand, being able to grow the table easily is important. Spreadsheet applications usually present you with an infinite canvas. This is behavior people know (and maybe even expect).

Continue reading …

Separating ReSwift Actions from UI Events

Teaser image

Today was the second time during the development of TableFlip that I started to implement a new feature in the wrong way: starting with an explicit event type that is triggered by pressing a button in the user interface. This is a 1:1 mapping of user intent to an event that performs changes in the model. Next time I’ll start from another point of view instead to not rush too many minuscule changes until I hit a roadblock and hate myself. Here’s what went wrong.

Continue reading …

TableFlip Closed Beta Invitations

Teaser image
screenshot of TableFlip
TableFlip’s current beta interface

I’ll send out a beta invitation to everybody on the TableFlip Newsletter this week. If you want to help me find quirks in the app and overall make it more usable, this is your chance!

Everyone who reports an issue will get a free license when the beta ends. Also, I’ll invite interested folks in batches, so you may not get your hands on the app this time but maybe in 2 weeks.

Join the Beta List

Tell your friends and in general everybody who’s using Markdown and/or deals with lots of tabular data in their work.

Check Boxes in AppKit

Check boxes in AppKit are realized with buttons. The API reads kind of weird, because the NSButton.state property does so many things, so here’s a simple subclass I do sometimes employ: Now it’s easy to use checkbox.isChecked = true. I’d even consider check() and uncheck() commands if I used this in many places to reduce the noise and clarify what’s going on further, maybe.

Continue reading …

Location Matters

The location of a piece of code always matters. I was fiddling with the Charts library today and found out that if you set a chart’s data to nil, it renders some informative text by default. My data source doesn’t pass nil but an empty array around, though, so I had to convert empty arrays to nil to make use of this feature.

Continue reading …

objc.io Books 30% Off

Teaser image
books screenshot

All 3 amazingly useful objc.io books are 30% off this week. Grab all three of them in a bundle and save even more.

If you use my link, I’ll even get a small kickback thanks to their affiliate program. I wholeheartedly recommend you take at least the time to read the samples. The team updates their ebooks regularly, and you’ll get a Swift 3.0 edition later this year, too.

Disabling Segments in a NSSegmentedControl in a Toolbar

This post is part of a series on getting NSSegmentedControl to work in your toolbars. Earlier this week I posted how to create a segmented toolbar item with 1 label for each segment. Now some options in TableFlip depend on context: without a selected cell, you cannot remove the selection, for example. So I disabled some segments and it looked alright:

Continue reading …

How to Create a Segmented NSToolbarItem like Apple Mail.app

Teaser image

Ever wondered how Apple Mail’s NSToolbar achieves the effect of individually labeled buttons shown in groups? Update 2018-11-23: I discovered a flaw in the target–action-mechanism of NSToolbarItems. They don’t fire if the label is hidden. This post’s approach is still valid enough, but is now part of a series of posts on the topic, with the 3rd one providing a fix:

Continue reading …

Configuration Objects and the Then Microframework

When parameter lists grow or two kinds of parameters seem to go together a lot, it’s time use the extract parameter object refactoring for greater good – then you can even specify sensible defaults.

This is a typical way to pass a set of options to an objects during initialization in a language like Swift. In languages like JavaScript or Ruby, dictionaries of key–value pairs can work just as well. Using dictionaries in Swift for this can be a pain, though.

Now Soroush wrote about a way that uses the Then microframework as a replacement for configuaration dictionaries. This way you don’t have to promote every property to the initializer’s list of parameters. Here’s a before and after, where you can see that without then you have to write a lot of repeating boilerplate:

// Before

struct FieldData {
    let title: String
    let placeholder: String
    let keyboardType: UIKeyboardType
    let secureEntry: Bool
    let autocorrectType: UITextAutocorrectionType
    let autocapitalizationType: UITextAutocapitalizationType

    init(title: String,
        placeholder: String = "",
        keyboardType: UIKeyboardType = .Default,
        secureEntry: Bool = false,
        autocorrectType: UITextAutocorrectionType = .None,
        autocapitalizationType: UITextAutocapitalizationType = .None)
        {
            self.title = title
            self.placeholder = placeholder
            self.keyboardType = keyboardType
            self.secureEntry = secureEntry
            self.autocorrectType = autocorrectType
            self.autocapitalizationType = autocapitalizationType
    }
}

let fieldData = FieldData(title: "Password", secureEntry: true)

Now with then, making non-mandatory properties mutable and getting rid of the boilerplate:

// After

struct FieldData {
    let title: String
    var placeholder = ""
    var keyboardType = UIKeyboardType.Default
    var secureEntry = false
    var autocorrectType = UITextAutocorrectionType.No
    var autocapitalizationType = UITextAutocapitalizationType.None

    init(title: String) {
        self.title = title
    }
}

let fieldData = FieldData(title: "Password").then({
    $0.secureEntry = true
})

That’s a Swift alternative to Ruby’s hash-based option initializers. There, the dictionary’s key is used as the setter’s name which is then invoked like so:

class Example
  attr_reader :name, :age
  
  def initialize(args)
    args.each do |k,v|
      instance_variable_set("@#{k}", v) unless v.nil?
    end
  end
end

e1 = Example.new :name => 'foo', :age => 33
#=> #<Example:0x3f9a1c @name="foo", @age=33>

Principles of Object-Oriented Design in Swift 2.2

Understanding Uncle Bob’s Principles of Object-Oriented Design (which resulted in the SOLID principles) is super important to really grasp the use of design patterns (like MVVM) and architectural patterns (like VIPER). It’s like the grammar for crafting proper object-oriented software.

And now here’s the good news: there is a Swift playground (and Markdown file to read online) that illustrates all the principles by Uncle Bob: The Principles of OOD in Swift 2.2

Check it out, take notes, and keep the principles close to your heart. They may save your life someday.

TIL You Can Cancel Enqueued GCD Blocks

Today I learned that you can cancel a delayed dispatch_block_t with the new dispatch_block_cancel (available since OS X 10.10/iOS 8.0). Thanks Matt for the post – here’s a Swift example:

let work = dispatch_block_create(0) { print("Hello!") }

# Execute after 10s
let delayTime = dispatch_time(DISPATCH_TIME_NOW, Int64(10 * Double(NSEC_PER_SEC)))
dispatch_after(delayTime, dispatch_get_main_queue(), work)

dispatch_block_cancel(work)
# Will never print "Hello!"

Note: canceling doesn’t work if the block is being executed.

If I knew that this API existed, I might not have used the very cumbersome approach from below in Move!.

Super-Weird Legacy Version of a Cancelable Delayed Block

For historic purposes, here’s an adaptation of the cancelable dispatch block you may find on the internet that I once have adapted for Swift:

typealias CancelableDispatchBlock = (cancel: Bool) -> Void

func dispatch(
        cancelableBlock block: dispatch_block_t,
        atDate date: NSDate
        ) -> CancelableDispatchBlock? {

    // Use two pointers for the same block handle to make
    // the block reference itself.
    var cancelableBlock: CancelableDispatchBlock? = nil

    let delayBlock: CancelableDispatchBlock = { cancel in

        if !cancel {
            dispatch_async(dispatch_get_main_queue(), block)
        }

        cancelableBlock = nil
    }

    cancelableBlock = delayBlock

    let interval = Int64(date.timeIntervalSinceNow)
    let delay = interval * Int64(NSEC_PER_SEC)

    dispatch_after(dispatch_walltime(nil, delay), dispatch_get_main_queue()) {

        guard let cancelableBlock = cancelableBlock else { return }

        cancelableBlock(cancel: false)
    }

    return cancelableBlock
}

func cancelBlock(block: CancelableDispatchBlock?) {
    guard let block = block else { return }

    block(cancel: true)
}

The trick is this: the delayed block delayBlock: CancelableDispatchBlock captures its context where a reference to cancelableBlock is included – but not set yet. Then you make the reference point to the delayBlock itself.

The actual canceling is a fake, though. The block is still called. It aborts early if the cancel parameter is true, though.

Hustling

I was confused about the term “to hustle” for quite a while, probably because I’m non-native. I found it in various books about startups and solopreneurship, and from the context I deduced it might have something to do with marketing. Shawn Blanc was the first to make sense of this: it usually means to do a lot of work. To break a sweat working towards your goals.

Now there’s nothing wrong with this. “If you want to succeed as hard as you want to breathe, then you will succeed.” That should by no means entail you stop sleeping at all and wear your body down. After all, you and your body are one.

That’s why I’d like to add a few items to Shawn’s list:

  • Start eating real food and stop swallowing garbage.
  • Give yourself the chance to detox; remove everything that may affect your brain for a while – porn, social media, coffee, tea, sugar.
  • Exercise and move every day. Walk for 30 mins if you can’t muster the strength for anything else.

A lot of people I met in tech are interested in body-hacking, life-hacking, and the like. Optimizing sleep for example. Or ditching processed food because, you know, better focus and stuff. This is the search for technical solutions (stuff you set up once and then do it like an automaton) when the underlying challenges are those a corporeal life itself presents.

The fundamentals are the same no matter if you want to be a healthy over-performer in tech or a professional athlete: push your limits and swing the pendulum back and forth from stress to relaxation: Fast and eat; exercise and rest; work and meditate. Your performance is not only about how quick you can throw together a working app. It’s also about how long you can excel at what you do before wearing out.

So take care, don’t overwork, don’t underwork, and push yourself on all frontiers in life at once.

Custom Enumerated Sequences in Just 1 Line of Code

In “Creating a Cheap Protocol-Oriented Copy of SequenceType (with a Twist!)” I created my own indexedEnumerate() to return a special kind of enumeration: instead of a tuple of (Int, Element), I wanted to have a tuple of (Index, Element), where Index was a UInt starting at 1. A custom CollectionType can have a different type of index than Int, so I was quite disappointed that the default enumerate() simply returns a sequence with a counter for the elements at first.

Continue reading …

Evaluate and Launch Your Idea With Small Steps

As you may know, I’m totally immersed in getting TableFlip ready to ship. By some random circumstance, I recently stumbled upon Paul Jarvis’s getting started post about online businesses.

I already read the hip books about startups: Startup Owner’s Manual (meh), Lean Startup (ok), $100 Startup (inspiring), Lean Entrepreneur (meh), Running Lean (good one) – you name it. I still found Paul’s action-oriented collection valuable to get started. It’s the little first steps that matter which I tend to forget sometimes.

With TableFlip, I wanted to know if a visual Markdown table editor would be something people liked. So I put together a landing page for it and asked around. By sheer luck I managed to get 300 subscribers in about a month. I’m excited to show them the first test build. – Sadly, I cannot say that I have any fancy techniques to share. Being connected to other people that love to re-tweet your announcements or post links to their blogs helps a lot. Nothing else has had any effect for me, like, ever.

I posted a link to Joa Allen’s recommendation to get in touch with truly loyal people with a free app MVP that solves 80% of their problems already.

The bottom line of all this is: Just. Do. It. You need feedback, so get something out as quickly as possible. Then you may be able to fend off starvation in the long run.

Outperforming the Competition

[U]nless your talent and skills absolutely dwarf those of your competition, the deep workers among them will outproduce you.
—Cal Newport, Deep Work

(via Shawn Blanc)

This is super relevant if you’re on your own or even starting to pursue a career in programming. It doesn’t matter how much time you spend. The intensity of focus counts. Call it myelin or what else you will: only deliberate practice will make you better. “Deliberate” means it’s challenging. And that you pay attention to the challenge. That you elaborate why you failed. All of this takes a bit of extra time, but the result is so much better than simply dashing through and hoping for the best.

It’s easy to leave the StackOverflow copy & paste “”coders”” behind.

That’s why I find Khuong’s 100 Swift projects or Patrick Bellot’s experiments in Swift so impressive. Everyone can do that.

I know for sure that I need to pick up a book on Core Image and Core Animation sometime, soon, because I have no clue how to use these frameworks. It’s not a blind spot. It’s a known weakness. Doing a challenging project in these areas will catapult my skill further towards mastering the craft.

Here’s my invitation to you: take a minute to evaluate where you stand. What does make you uncomfortable? Take note of that. Make these things projects. Then do or plan some research for each to find out how to tackle these known unknowns. Then execute.

Better Sliding Menus

In a recent usability post of Raluca Budiu, the common mobile app pattern of sliding menus is criticized: when the menu button is at the left edge and the content slides away to the right, then hiding the menu again requires the user to move her hand, and reading the menu items requires her to move her finger out of the way. With fat fingers, this is even more of a problem.

Continue reading …

How to Abort a Chain of Rake Tasks on Error

I use nanoc as my static site creator for this blog. It’s written in Ruby, my favorite scripting language. And so I use a Rakefile to automate most things, like generating a fresh copy of the site and deploying it to my server. Only last week did I find out how to make Rake not continue when a part of its tasks failed. Most of the stuff I use is wrappers around shell commands with a few system notifications sprinkled in. $? does capture the latest shell call’s return value (kudos dnsimple.com):

Continue reading …

How to Get Started with Swift: Write New Tests in Swift

Daniel Jalkut of MarsEdit fame is slowly getting up to speed with Swift. I have a few Swift-only projects already (Move!, TableFlip and secret in-progress ones). On top of that, every feature I add to the Word Counter is a Swift module, too. The main code of the Word Counter is still in Objective-C, though.

Integrating new types to the project using Swift is awkward. There’re things you can only use in one direction. Most if not all Objective-C code can be made available for Swift and works great. The other way around, not so much. Also, Objective-C imports from the -Swift.h file won’t be available in Swift-based test targets. So you’ll have to isolate these even further, create wrappers, or whatever. Porting a class to Swift can work, but the side effects on testing make it harder.

I like Daniel’s advice to write your unit tests in Swift if you’re still not certain if you should make the switch to this new and volative language. It’s a good idea to get your feet wet.

Considering the problems I ran into with the Word Counter, though, I wouldn’t know how, honestly.

What I Did When I Found Emojis in Strings Always Lost the Last Byte

Teaser image

Took me a while to not only figure it out but actually fix that Emojis are encoded in a special way using UTF-8.

If things are well on your side, you’ll see a “thinking” emoji here: 🤔

I wanted to be able to enter these in text files, read them in, display them, and save the contents in a way that they are visible in the text file again. Sounds trivial, but every double-encoding trick I found on the web resulted in escaping the unicode char codes (\ud83e etc.)

Reading stuff in worked with basic NSUTF8StringEncoding, but writing not so much. Turns out the last byte of a line was stripped for some reasen. Turns out all of this was my fault. Thanks to playgrounds for giving me feedback about matching encoded data.

Emoji seem to take 7 bytes when you look at the UTF8-encoded NSData representation. In my tests, it seemed that when an emoji was the last character in a line things went broke. I had to enter characters after it to work. These characters wouldn’t be stored, but at least the emoji would be visible.

My fault was that I was padding strings to have a certain length like so:

extension String {
    func padded(length length: Int, filler: String = " ") -> String {
        return self.stringByPaddingToLength(length, withString: filler, startingAtIndex: 0)
    }
}

I was not using NSString but native Swift Strings, so I expected things to go well. But they didn’t. I don’t know for sure why this method from foundation wreaks havoc with strings containing emoji, but it sure did. At first, the fact that 1 emoji character consists of 2 UTF8-encoded unicode values at once resultet in truncating the line. Even when I increased the padding to 2x the visible character count, the last visible character was lost in the end.

I found a cheat: calculate the byte size of the given string and fill up manually:

extension String {
    func padded(length length: Int, filler: String = " ") -> String {
        let byteLength = self.lengthOfBytesUsingEncoding(NSUTF32StringEncoding) / 4
        let paddingLength = length - byteLength
        let padding = String(count: paddingLength, repeatedValue: Character(" "))
        return "\(self)\(padding)"
    }
}

Works like a charm and doesn’t use data. TableFlip beta testers will probably find more edge cases, but at least the app doesn’t crash or ruin your files.

Productivity Tips for Programmer Solopreneurs

Vikas Thakur is an INTP personality type – very common among programmers I’d say. He wasn’t good at micro managing himself until he found the tools to prevent bad habits (casually browsing the web) and track his progress to gather intelligence about how he works. He found 5 tools and 5 habits to do the trick (among them my Word Counter).

If you suffer from unwillingly checking your Twitter feed, have a look at his tips. There may be something for you, too. My flat mate un-learned wasting time on YouTube and Facebook with a tool last year. I recommend you give it a try and see for yourself if that sounds like you.

The Power of Guard

Here’s a guard statement with many different kinds of features by Benedikt Terhechte:

guard let messageids = overview.headers["message-id"],
    messageid = messageids.first,
    case .MessageId(_, let msgid) = messageid
    where msgid == self.originalMessageID
    else { return print("Unknown Message-ID:", overview) }

I love guard statements. It helps make code much more readable and keep methods un-intended.

I feel less amorous about guard-case and if-case matching, though:

if case .Fruit = foodType { ... }

This reads an awful lot like Yoda conditions where you place the constant portion on the left side. This isn’t even a typical boolean test (which would use the equality operator ==) but a failable assignment (=). I can force myself to read and write it this way, but it always feels backward to me. It took me quite a while to memorize this, which I found surprising, as it was comparatively easy to learn Swift in the first place.

Apart from the guard-case portion, the example contains your standard guard-let unwrapping. The else clause is special though, and I didn’t know this would work:

guard someCondition else { return print("a problem") }

When the function is of return type Void, you can return a call to another void function. This is shorter than splitting these two instructions on two lines, but it’s too clever for every reader to understand. print("a problem"); return is just as compact, as Terhechte points out.

Refactoring to Clean Value Transformations in Swift

Daniel Steinberg’s presentation “Ready for the Future: Writing Better Swift” teaches us a lot about readable code. He refactors a calculation into many functions with very specific responsibilities. The resulting functions are super slim.

The result is this:

let lastWeeksRevenues = lastWeeksSales
                        » anArrayOfDailySales
                        » replaceNagiveSalesWithZeroSales
                        » calculateRevenuesFromSales

When you read that code it should be very clear what’s going on. The function names communicate their intent.

Now the implementation:

func anArrayOfDailySales(rawSales: AppSales) -> [Int] {
    return rawSales.map{$0}
}

func replaceNagiveSalesWithZeroSales(sales: [Int]) -> [Int] {
    return sales.map(negativeNumbersToZero)
}

func negativeNumbersToZero(number: Int) -> Int {
    return max(0, number)
}
    
func calculateRevenuesFromSales(sales: [Int]) -> [USDollars] {
    return sales.map(revenuesInDollarsForCopiesSold)
}

func revenuesInDollarsForCopiesSold(numberOfCopies: Int) -> USDollars {
    return numberOfCopies
        » revenuesForCopiesSold
        » toTheNearestPenny
}

let unitPrice = 1.99
let sellersPercentage = 0.70

func revenuesForCopiesSold(numberOfCopies: Int) -> USDollars {
    return Double(numberOfCopies) * unitPrice * sellersPercentage
}

infix operator » {associativity left}

func »<T, U>(input: T, transform: T -> U) -> U {
    return transform(input)         
}

Apart from the » operator which merely changes foo.map(bar) to foo » bar, the functions are very small, easy to read. This reminds me of the result of 3/4 of Sandi Metz’s arbitrary rules for writing Ruby code:

  1. Classes must be shorter than 100 lines
  2. Methods must be shorter than 5 lines
  3. Always pass less than 4 parameters into a method

Of course the result is a lot of functions for a rather simple algorithm. But it works well because it is easy to read in the long term. Even newcomers can grasp what’s going on without knowing much about the language or typical Cocoa-programmer conventions.

Bonus: you can unit test each function to check if the parts of the overall algorithm works as expected.

The Swift Developer’s Cookbook Review

Teaser image

Although I knew there’s a “cookbook” book series, I haven’t read any of these before I read Erica Sadun’s The Swift Developer’s Handbook. The code listings are called “recipes”, and most of the time rightly so: I bet I copied about a dozen of the recipes into my own handy code snippet index to extend Swift’s capabilities with super useful things like safe Array indexes.

Continue reading …

5 Heuristics for “I have a complicated nested view controller setup. How do I handle passing data?”

That’s a recent question from the comments put in my own words. A view model that encapsulates the display state sounds promising at first. But when you don’t have a simple view that displays one thing, how do you model that in code? How do you model a sequence of view controllers, for example a more complex checkout process?

Continue reading …

Swift Selector Syntax Sugar

The gist of the article is that we can omit the verbose #selector syntax by adding a convenience property:

private extension Selector {
    static let buttonTapped = 
        #selector(ViewController.buttonTapped(_:))
}
...
button.addTarget(self, action: .buttonTapped, 
    forControlEvents: .TouchUpInside)

I’d make that not private but internal and group these in a struct to separate them from other Selector stuff:

extension Selector {
    // One for each view module ...
    struct Banana {
        static let changeSizeTapped = 
            #selector(BananaViewController.changeSizeTapped(_:))
    }

    struct Potato {
        static let peelSelected = 
            #selector(PotatoViewController.peelSelected(_:))
    }
}

// ...

button.addTarget(self, action: .Potato.peelSelected, 
    forControlEvents: .TouchUpInside)

Great tip!

Blocks: Useful to Perform Actions In Context

Something short and sweet I want to share with you because I love how it reads: restoringSelection is a function that takes a block and performs whatever the block does while restoring the current selection in a table view (here: NSTableView). Here’s the implementation. The resulting code from above reads so much nicer than querying selection() first and restoring it afterwards. It communicates very clearly that some state from before will be preserved (or restored).

Continue reading …

VIPER by Experience: How to Set Up an iOS Project

Found a very detailed article about how a team implemented VIPER in their iOS project written by Michał Wojtysiak & Bartłomiej Woronin.

They discuss general project architecture, using tools to generate module files, and how passing data from one Wireframe to another works in their app.

I haven’t used VIPER in an iOS app, yet, but I used the concept in the Word Counter. There, nothing’s disposed after setup, so I have all Wireframes and their components setup once upon launch. The authors use Wireframes as factories for view controllers.

A Note about Syncing Changes: Where to Handle Sync Events

Further down, under “How to deal with listening changes from backend?”, the authors show how synchronization changes take effect.

  • The SynchronizerService merges changes into the Core Data stack,
  • the Core Data Stack sends a notification,
  • the Interactor receives the notification,
  • and changes are then pushed through the Presenter to the View.

This works, but I find the decision to be weird. Now the Interactor prepares data when requested and pushes changes upon synchronization events.

Usually, the Presenter is created in such a way that it both presents data to the view and handles events from the view. You can split this into two objects, let’s say Presenter and EventHandler. Then it becomes clear that the EventHandler can deal with events both from UI interaction and from syncing. It’s the best fit to translate any event into a command for the Interactor so it does its job.

How I Toggle or Switch 2 NSMenuItems from the Main Menu

I thought it’d be straigthforward and simple to make a NSMenuItem from the main menu implement a toggle – be it a checkmark or switching “Show X” with “Hide X” conditionally. Turns out that’s not quite as simple as I had hoped. Cocoa bindings would work but make things complicated. Most stuff on the web uses view tags to find items in menus. That’s not my favorite solution for anything. menuNeedsUpdate wasn’t called when I had hoped it would, either. So I tried a few different setups and settled with a boring and verbose way to switch “Show X” and “Hide X” depending on a boolean flag the current NSDocument window exposes.

Continue reading …

Announcing TableFlip

Teaser image

I’d like to officially announce my next project: TableFlip. Open any Markdown file with TableFlip and you can visually edit the tabular data included. Save and the Markdown file is updated. It’s that simple. It’s also Markdown-aware simple table data editing app. It’s fast and lean and pretty. No need to fire up monstrosities like Excel for Mac or even Apple’s own Numbers to edit simple data that naturally fits the 2D-arrangement of a table.

Continue reading …

How to Create Fixture Files for Unit Tests

This is mostly a reminder for my future self: It doesn’t suffice to create a TXT file and add it to the target in the file inspector (⌘⌥1) to be able to read it as part of the bundle. You also have to drag it into the “Copy Bundle Resource” build phase of the target so it get, well, bundled into the product. (In my case, it was the test target.)

screenshot of Xcode
The .md file was part of the test target but loading it from the NSBundle failed until I added it to the proper Build Phase
  1. Create an empty file or add an existing file to the target’s group in Xcode and make it part of the proper target,
  2. drag it into “Copy Bundle Resources” build phase,
  3. load it using NSBundle(forClass: TheTestCase.self).URLForResource("filename", withExtension: "txt").

Storing PLIST or JSON files for structured data works just as well. I happen to require plain text flavors most of the time and always wonder why the loading fails for a couple of minutes.

Creating a Lens for an Object to Provide a New Public Interface

I’m back from my vacation and very deep into programmin already. Before I left, my subconscious mind brought up the notion of a Lens (functional programming) while I was modelling tabular data in Swift and I think this is a very cool approach to keep value types clean and easy to test. I use lenses in my current project to provide a specialized interface to operate with the table. The lenses provide access to column and row iterators, independent of the table’s underlying data structure. This way the table doesn’t have to worry about all this stuff.

Continue reading …

A Vacation Week – 20% Discount While I’m Away!

palm trees
vaycay by Philipp Richter. License: CC-BY-NC 2.0

I’ll be on vacation for the next week. Maybe I cannot hold my breath and publish a post nonetheless, but I’ll try not to. Either way, for the next week everything from my store is 20% off so you can have fun while I’m away.

Apps

  • The Word Counter to increase writing productivity,
  • Move! to not die from sitting in front of your computer.

Books

Enjoy the new and shiny Indie Mac Developer book bundle, including:

– both of which you can buy on their own, too, of course, if you don’t need both.

Not related to programming but rather writing: Minimal Writing on the Mac, too, is on discount.

Reusable View Components from Nibs

Just found this today in a Slack channel. It seems we can actually reference and re-use Xib files by overriding awakeFromCoder!

If we are loading from placeholder view, we create a real view and then we transfer some common properties from it and all it’s subviews, then we just return that instance in place of placeholder, otherwise we just return normal view (This method is implemented on NSObject so we can call super, but this still should be done with method swizzling instead of category smashing).

There’s a sample project on GitHub. Let’s tear it apart.

It works like this:

const int kNibReferencingTag = 616;

@implementation UIView (NibLoading)
// ...
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
  if (self.tag == kNibReferencingTag) {
    //! placeholder
    UIView *realView = [[self class] loadInstanceFromNib];
    realView.frame = self.frame;
    realView.alpha = self.alpha;
    realView.backgroundColor = self.backgroundColor;
    realView.autoresizingMask = self.autoresizingMask;
    realView.autoresizesSubviews = self.autoresizesSubviews;

    for (UIView *view in self.subviews) {
      [realView addSubview:view];
    }
    return realView;
  }
  return [super awakeAfterUsingCoder:aDecoder];
}

When the kNibReferencingTag is set, the current instance (self) is treated as a prototype. From that prototype we transfer common properties to the realView which is properly loaded from a Nib. That means it doesn’t go the kNibReferencingTag path but the usual path, deferring to super.

The sample app contains SomeView with its own Xib that should be reused.

In the app’s Xib, we have a scene that uses it as follows:

<scenes>
    <!--View Controller-->
    <scene sceneID="4">
        <objects>
            <viewController id="2" customClass="ViewController" sceneMemberID="viewController">
                <view key="view" contentMode="scaleToFill" id="5">
                    <rect key="frame" x="0.0" y="20" width="768" height="1004"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                    <subviews>
                        <view tag="616" contentMode="scaleToFill" id="VTu-Cz-9kE" customClass="SomeView">
                            <rect key="frame" x="113" y="216" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                        <view tag="616" contentMode="scaleToFill" id="7te-Q6-moz" customClass="SomeView">
                            <rect key="frame" x="199" y="446" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                        <view tag="616" contentMode="scaleToFill" id="7vx-xh-xRD" customClass="SomeView">
                            <rect key="frame" x="375" y="231" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                    </subviews>
                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                </view>
            </viewController>
            <placeholder placeholderIdentifier="IBFirstResponder" id="3" sceneMemberID="firstResponder"/>
        </objects>
    </scene>
</scenes>

I know, Xib files aren’t the best to read. Here’s what it boils down to:

  • Create a scene using a view controller of type ViewController.
  • In its main view place 3 subviews …
    • of type SomeView,
    • all with the tag 616,
    • and a few standard color properties – apparently all set to white. It doesn’t matter anyway since the SomeView.xib will dictate what it really looks like.

Unlike @IBDesignable components, you won’t have any live preview in Interface Builder. Just empty placeholder boxes.

Featherweight Router

I read Karl Bowden’s Featherweight Router TL;DR and kind of like how routes are handled. The setup looks complicated, though:

let someRouter = Router(aDelegate).route("animal", children: [
    Router(aDelegate).route("animal/mammal", children: [
        Router(aDelegate).route("animal/mammal/cow"),
        Router(aDelegate).route("animal/mammal/pig"),
    ]),
    Router(aDelegate).route("animal/fish", children: [
        Router(aDelegate).route("animal/fish/salmon"),
        Router(aDelegate).route("animal/fish/trout"),
    ]),
])

// Using regex's for matching
let someRouter = Router(aDelegate).route("animal", children: [
    Router(aDelegate).route("animal/\\w+", children: [
        Router(aDelegate).route("animal/\\w+/\\w+")
    ])
])

Child routers carry the path component of the parent with them. Also, this is very verbose. I imagine a more terse version, like:

// Assuming `aDelegate` is used for all of them and passed along,
// let's omit it during setup of sub-routes:
let router = Router(aDelegate) { router
    router.route("animal") { router in
        router.route("mammal") { router in
            router.route("cow")
            router.route("pig")
        }
    }
}

Or let’s say some part is variable, like viewing a user profile:

let userRouter = Router(aDelegate) { router 
    router.route("users") { router in
        router.route(.Parameter("userId", "[0-9]+")) { router in
            router.route("friends")
            router.route("photos")
        }
    }
}

Then the route users/12345/friends will parse and the “12345” part will be available in a params dictionary under the key userId.

I haven’t given routers much though in the past but I think I’ll explore the possibilities of routing and existing libraries some more.

Import Parts of a Module

Did you know you can import only parts of a module? Found this in the Swiftz sample codes:

let xs = [1, 2, 0, 3, 4]

import protocol Swiftz.Semigroup
import func Swiftz.sconcat
import struct Swiftz.Min

//: The least element of a list can be had with the Min Semigroup.
let smallestElement = sconcat(Min(2), t: xs.map { Min($0) }).value() // 0

import protocol or even import func were very new to me. Handy!

rethrows in Swift

Rethrows saves us a lot of duplicate code. Look at my naive approach to write an iterator in Swift 1 from last year which I later extended for throwing with Swift 2:

extension Array {
    func each(@noescape iterator: (Element) -> Void) {
        for element in self {
            iterator(element)
        }
    }
    
    func each(@noescape iterator: (Element) throws -> Void) throws {
        for element in self {
            try iterator(element)
        }
    }
}

This can be written as a single method with Swift 2 as I later found out:

extension Array {
    func each(@noescape iterator: (Element) throws -> Void) rethrows {
        for element in self {
            try iterator(element)
        }
    }
}

The rethrows keyword makes the method a throwing one depending on the closure you pass in. Only if the closure throws each will throw, too. The compiler will know what happens – just like generic functions are write-once, use-many-times.

Of course I later found out that Swift 2 came with forEach already bundled in. So there’s no use in this anymore except for this very illustrative blog post to remember that throws/rethrows is different from throws/throws.

How do You Really Mock Objects You Don’t Own? You Replace Them with Adapters

Teaser image

How do you test NSURLSession properly? After all, using it in tests directly will hit the servers; that’s not what you want to do 1000s of times per day. Even if you use a localhost based server replacement the tests will be slower and potentially error-prone as the server replacement may not be 100% accurate. Anyway – there’s a popular series of posts about that topic. There, you’ll learn how to mock NSURLSession in your tests. I think the advice is good to move on quickly, but it only shifts the problem slightly out of sight. There are better alternatives.

Continue reading …

DevMate is Completely Free Now

When DevMate launched, I dabbled with the backend a bit and I really liked it. They use FastSpring for the store and enabling DevMate to integrate into your FastSpring account is very simple.

It seemed to be kind of expensive, though. Since then, they changed the pricing model once or twice and made the platform more attractive to upcoming indies and teams with a lower budget. Now it’s free.

Their SDK seems to provide easy integration. I think I’ll check it out with my next app to tell you more about the details. I just hope they’re doing well – lowering the price could just as well mean that they try to attract more devs because it doesn’t pay off to run the platform at the moment. (I think I’ll just ask them to be sure.)

Piezo Exits the Mac App Store

Rogue Amoeba develop lots of popular software. Now Piezo 1.5 exits the Mac App Store.

While the App Store has many shortcomings, it’s the onerous rules and restrictions Apple has for selling through the Mac App Store which pose the biggest problem. The type of software we make is precluded from being sold through the store, particularly now that sandboxing is a requirement, and Apple has shown no signs of relaxing those restrictions. Fortunately, unlike iOS, the Mac platform is still open. We’re able to distribute and sell direct to our customers, right from our site. We’ve got almost 15 years of experience and success doing just that, and we have no plans to stop.

Their apps that work on the App Store stay there.

Shameless self promotion: Are you worried about the recent trend of abandoning the MAS? I wrote a book about publishing apps outside the Mac App Store. There’s nothing you have to fear. It’s fun.

Publish and Subscribe — Decoupling Deep View Hierarchies from Event Handlers

Imagine a complex view with many sub components. This is more common in Mac apps where a window contains multiple panes, lists, graphs, whatever. How do you react to interactions 5 levels deep? Let’s say you avoid massive view controllers which do everything on their own and want to encapsulate event handling outside the view hierarchy – what should you do?

Continue reading …

Extract Private Functions as Collaborators

“Using a private function means having a hardwired link to an anonymous collaborator. Over time, this will slowly hurt more.” (@jbrains) I was thinking about this the other day when I wrote tests for a presenter. It receives a date, formats it, and makes the view update a label with the result. Simple. (The real thing actually does a bit more, but that doesn’t matter much.)

Continue reading …

Symmetry

At first, this was all there was:

protocol DisplaysDateRange {
    func showDateRange(dateRange: DateRangeData)
}

class DateRangeViewController: NSViewController, DisplaysDateRange {
    @IBOutlet var dateRangeButton: NSButton!

    func showDateRange(dateRange: DateRangeData) {
        dateRangeButton.title = dateRange.range
    }
}

Then I implemented a sub-view controller and delegated to it, too:

class DateRangePickerController: NSViewController, DisplaysDateRange { 
    // ... 
}

class DateRangeViewController: NSViewController, DisplaysDateRange {
    @IBOutlet var dateRangeButton: NSButton!
    @IBOutlet var dateRangePickerController: DateRangePickerController!

    func showDateRange(dateRange: DateRangeData) {
        dateRangeButton.title = dateRange.range
        dateRangePickerController.showDateRange(dateRange)
    }
}

Then, by habit, I remembered Kent Beck’s advise to keep symmetry high for clean and maintainable code:

class DateRangeButton: NSButton, DisplaysDateRange {
    func showDateRange(dateRange: DateRangeData) {
        title = dateRange.range
    }
}

class DateRangeViewController: NSViewController, DisplaysDateRange {
    @IBOutlet var dateRangeButton: DateRangeButton!
    @IBOutlet var dateRangePickerController: DateRangePickerController!
    
    func showDateRange(dateRange: DateRangeData) {
        dateRangeButton.showDateRange(dateRange)
        dateRangePickerController.showDateRange(dateRange)
    }
}
petals
Photo credit: Layers of petals by n.a.t.u.r.e. License: CC BY-NC-ND 2.0

Sure, now there’s a subclass of NSButton that doesn’t do much and will not be reused in the app. But the intent of delegating DateRangeData to the sub-components is clearer.

Clean and maintainable code will help you see what’s going on when you read the code. title = dateRange.range doesn’t convey everything showDateRange(dateRange) does.

1 Criterion to Determine if You Should Write Unit or UI Automation Tests

Teaser image

Xcode now offers two kinds of tests natively. You don’t have to rely on 3rd party JavaScript libraries anymore to automate the iOS simulator and assert view conditions. So with the advent of native UI Automation tests, can you rely on them to verify your app works? Here’s the two sides of the 1 criterion you’ll ever need to find out:

Continue reading …

Always Write Functions to Cope with all Possible Parameter Values

Matt Galagher is back writing at Cocoa with Love. His goal is maintainability, which is the greatest of all, I think. It’s easy to copy code samples together to create an app, bur it’s hard to create a product you can keep alive and make better over years. In that vein, his first article, “Partial functions in Swift, Part 1: Avoidance”, includes a lot of details why partial functions will hurt you. This is a great topic. Read his post for the basic set theory involved.

Continue reading …

Make Money Outside the Mac App Store now Available on Amazon

book cover

My e-book about creating and selling apps for Mac without the Mac App Store is now available on amazon.com if you prefer a print edition!

Why does print cost less?
The digital edition will be updated regularly with the latest Swift syntax. Further editions and major revisions are free for customers, too. I can’t do that with a print edition on your bookshelf, obviously. That’s why.

It feels weird, I know, because paper costs money and print book feel more precious. I’m making about 50% less with each sale, so there’s quite some cost involved printing the book. The feeling of physical good in your hand is part of the perceived value, and everyone would tell me I should factor that in, but I’m a bad businessman. It’s the right thing to do. Why should you pay more for something with less long-term value only because my costs are higher?

Move! Review at Softpedia

Teaser image

My humble work break timer Move! has been reviewed by Catalin Chelariu over at Softpedia. I didn’t find any Twitter account or anything to thank him, so here it is: thanks for the review!

Catalin had one wish, though:

However, it would be great if there was an option to postpone the break, as it simply may not be possible to interrupt your current activity in certain situations.

I have to say that I totally understand where this comes from – I used AntiRSI and similar software in the past which offered a postpone button. It was useful. But it was also opening the doors to hell.

So I’m sorry to say that if your job demands you to sit down for whatever reason, then Move! isn’t going to be your app. It’s made for everyone, because everyone needs to get up more often. 30mins really isn’t that bad. Some corporate environments don’t care about your health, though, so you may need to increase the work duration.

What I wish for this app myself is the ability to start a break early, i.e. when I have to leave the desk for a while. Or a setting for work hours, so that it doesn’t interfere me watching a movie after 9 p.m., for example.

Mind Node adds Tasks

screenshot of Mind Node

I love Mind Node for Mac. Now they added tasks. I think that’s weird, but I can see how this is useful for some people. You can devise plans and operate on them without having to export the outline to a task management application, for example.

It looks great and maybe I can use this for a little side-project which doesn’t really need traditional taks (which I put into OmniFocus) but could benefit from checking off items nevertheless.

Flow Controllers to Replace Segue-based View Transitions

Krzysztof Zabłocki wrote about the concept of “Flow Controllers”. Assimilating the concept, I imagine they’re similar to the bootstrappers I use during app launch, only Krzysztof says there’s just one initial flow controller after launch while the others are used when transitions need to take place.

Separating state from transitions is a higher-level goal of architecting apps – and is especially amiss in UIViewController-centered iOS apps. “Flow Controllers” encapsulate the change or transition. This includes setting up the view controller according to the presentation needs:

  • Configuring view controller for specific context - e.g. different configuration for an Image Picker shown from application Create Post screen and different when changing user avatar
  • Listening to important events on each ViewController and using that to coordinate flow between them.
  • Providing view controller with objects it needs to fulfill it’s role, thus removing any need for singletons in VC’s

The singleton Krzysztof talks about is the usual way app state is modelled.

Here’s a slightly modified example to illustrate how a flow controller manages transitions between view controller scenes with configureProgramsViewController, configureCreateProgramViewController, or similar:

func configureProgramsViewController(
        viewController: ProgramsViewController, 
        navigationController: UINavigationController) {
        
    viewController.state = state
    
    // Add button action callback to show the next scene
    viewController.addProgram = { [weak self] _ in
        guard let strongSelf = self else { return }
        
        let createVC = // recreate a view controller, e.g. from a Storyboard
        strongSelf.configureCreateProgramViewController(createVC, 
            navigationController: navigationController)
        navigationController.pushViewController(createVC, animated: true)
    }
}

The flow controller owns the state here and takes care of pushing view controllers onto the navigation stack. This will not work with segues. It’s a replacement for them.

ReSwift, Law of Demeter, and Another Level of Indirection

Teaser image

Benjamin Encz’s presentation “Unidirectional Data Flow in Swift” about ReSwift features global app state: there’s one AppState type that acts as the facade to model and navigation state which is the single point of truth of every state in the app. This is a game changer when you suffer from massive view controller syndrome. In this post, I’d like to show you how he envisions the state of an app and what a next step could look like.

Continue reading …

Events as Declarative State

Teaser image

I think I found something better than closures to handle events. Instead of dispatching closures that are themselves the changes that should be performed, simply declare the change.

enum Action {
    case ResizeBanana(BananaId, Size)
}

Now you need some kind of action handler, which Benjamin Encz calls “reducer” in his presentation “Unidirectional Data Flow in Swift”. Think of a list of reducers as a Chain of Responsibility only without the final consummation of the action. It is passed throughout the whole responder chain. Why reducer? Because they operate similar to the reduce function. The end result will be the combined result of all reducer’s mutations.

This is cool, because no component needs to know what such an action entails – none except the appropriate reducers.

If closures were great because where you type them you can see what is going on (more like “how” in my opinion), a simple action enum is even simpler, telling what should happen.

Works well with CQRS, I imagine. Will have to write a demo app using CQRS sometime to validate.

The current project is called ReSwift and code is available on GitHub.

Extending Types with a Conversion Factory: Where Should You Put It?

In a post about the Swift reflection API, I found the conversion code from a Bookmark struct to a Core Data object interesting. Let’s call the latter ManagedBookmark.

What puzzles me: which object should be responsible for the adaptation from one to the other?

  1. Bookmark converts itself to a NSManagedObject using a NSManagedObjectContext you also have to pass in. (That’s what Benedikt did in his post.)
  2. ManagedBookmark provides an initializer or other factory taking in a Bookmark and, as always with managed objects, a NSManagedObjectContext.

Option 2 is pretty clear. Using Bookmarks public interface, the managed object will set its attributes. This requires a NSManagedObject subclass wheras option 1 can work with a dictionary of values.

My main worry is that in option 1 Bookmark, a value type of the application, has to have knowledge about Core Data. Usually we’d fare better if we separate Core Data from our own model.

With extensions in Swift (and categories in Objective-C) we have the power to add new behavior to existing types in other locations. Does this help?

Extending a type in a different file hides that detail at first sight – but the extension, when it’s not private, is available in the rest of the code base, too. It just appears as if you put the code in the type definition itself.

Now if Bookmark is included in a “Bookmarking” module you import, an extension can add behavior without mixing Core Data visibly into the model layer. The Bookmarking module will not get altered when you extend one of its types in the client code.

I like organizing Swift code in modules because the boundaries are very strict. You cannot cheat yourself into mixing responsibilities and blurring boundaries that easily.

I’ll be writing a Word Counter Swift module fully East-Oriented

Teaser image

The Word Counter is my biggest software project so far, and it’s growing. To add features, I discovered the use of Swift modules with joy. I can write code for all levels of the new feature in isolation in a new project that compiles fast. Later I plug the resulting project and module into the Word Counter, et voilà: feature finished.

Continue reading …

How to Couple UITableView Cell Identifiers and View Models

Rui Peres proposes to make UITableViewCell view models the topmost model data. Traditionally, Cocoa developers stored something in arrays that corresponded to the indexPath of a cell. In principle, this qualifies as “model” data already, but it’s not yet a view model. In practice, it can even be something different than a view model entirely – and make your view controllers slimmer!

Continue reading …

Separating State from State Changes

Reflecting on a recent change of the Word Counter’s file monitoring module, I think I re-discovered a commonly advised pattern in my code: to separate state from state changes. There’s an object that knows how to handle files based on extension: plain text files’s words are counted differently than Word or Scrivener files. Call it Registry. Previously, this was set up once and didn’t change. Now I wanted to make this configurable so users can add custom plain text extensions. This means changing that object’s state.

Continue reading …

How Closures are a Better Event Handler Protocol Alternative

I don’t like the way I tend to create view controller event handlers. They are almost always just a sink for methods which have nothing in common conceptually but are tied together because of the view’s capabilities. So I began experimenting. Closures can encapsulate changes. This works well with callbacks for Repositories which fetch entities from your data store. Instead of returning them, you can pass them forward:

Continue reading …

iRamDisk May Speed Up Your Xcode Compilation Times

Teaser image

I code on a late 2011 Mac Mini with 8 GB RAM and a 256 GB SSD. This machine is a ton faster than my old MacBook Air was. Compilation still takes time, but it seems that iRamDisk helps a bit.

Lately I wondered if I could cut down the 30s compilation time (3mins with a clean build folder) if I had a Mac Pro, or MacBook Pro, or iMac, or whatever next tier device. Faster cores, more cores, doesn’t matter. But buying a Mac for $3k is out of question at the moment. So I’ve been looking for other tricks.

The only thing that’s faster than a SSD is RAM. That’s when I found the app iRamDisk. It offers an option to move the derived data folder to a virtual disk in RAM. It seems I can reduce the clean build time from 3mins to 2mins with that. Xcode needs about 1.5GB derived data for the Word Counter – at least that’s how big I had to make the RAM disk to not get filled quickly. The overall memory pressure is a bit higher, the Mac is using swap more, but compilation becomes faster at last.

There’s a downside, too: after every reboot the RAM disk is empty, so Xcode has to index the project again and compile fresh at least once a day. Depending on your usage this can be annoying or not be a problem at all.

You can download a trial from the website or buy it for $19.99 on the Mac App Store.

Get Your App Indexed by Google

I did know that universal links help integrating web content and native app scenes: regular web links may show the content in the browser on most devices but magically open the content within your native app when it’s installed. The prime example I knew was IMDB’s movie database, but it obviously works for recipes as well.

Now I read about a Google App Indexing SDK. Before universal links, it tried to achieve the same effect. But what does it do nowadays?

The source code isn’t prominently linked anywhere. I went to the CocoaPods spec and downloaded the source tar file (at the bottom of the spec).

The “source” contains a framework which publishes two classes, GSDAppIndexing and GSDDeepLink. There’s a sample iOS app on GitHub by Google as well.

You use GSDAppIndexing to register your app with its iTunes ID – but the sample application doesn’t do that at all. The docs indicate this is needed to expose content to crawlers, though. The sample app does handle links in AppDelegate:

var currentDeepLink = String()
    
func application(app: UIApplication, openURL url: NSURL, options: [String : AnyObject]) -> Bool {
    let sanitizedURL = GSDDeepLink.handleDeepLink(url)
    currentDeepLink = sanitizedURL.absoluteString
    return true
}

Instead of routing, it only stores the link for display purposes. There you see what GSDDeepLink is good for: extracting the real deep links from the Google search deep link call.

What’s it good for?

It will show deep links (perhaps more prominently?) when you browse Google on Mobile Safari. In other words, regular visitors with a Mac probably won’t notice any difference.

The following is the expected URL scheme according to the GSDDeepLink.h file, split up into multiple lines for reading convenience:

gsd-<scheme>://<appstore-id>/
    ?google-deep-link=<url-encoded-original-deeplink>
    &google-callback-url=<url-encoded-callback-url>
    &google-min-sdk-version=<minimum-sdk-version>

And an example:

 Annotation:
 ios-app://544007664/vnd.youtube/www.youtube.com/watch?v=aISUYHTkTOU
 
 Original Deeplink:
 vnd.youtube://www.youtube.com/watch?v=aISUYHTkTOU

 Callback URL:
 googleapp://
 
 Final URL:
 gsd-vnd.youtube://544007664/
     ?google-deep-link=vnd.youtube%3A%2F%2Fwww.youtube.com%2Fwatch%3Fv%3DaISUYHTkTOU
     &google-callback-url=googleapp%3A%2F%2F
     &google-min-sdk-version=1.0.0

The following is just totally made up: I assume the GSDDeepLink helper actually sends back some statistics to Google. Otherwise I wouldn’t know what the wrapped URL would be good for at all. (Suggestions welcome.) GSDDeepLink does overlay the status bar for a short while according to the header documentation so users may return to the search results.

I still don’t get the benefit from using Google’s framework in my projects. When users reach my website via Google, the native app is expected to open automatically anyway. So there’s only the formatting of app-related search results left as a benefit as screenshots indicate.