Tuesday, June 2, 2020

Whose Lives Matter?

In 1838, Missouri governor Lilburn Boggs issued the "Extermination Order" in response to rising tensions between incoming Mormon settlers and local residents. It read, in part:
The Mormons must be treated as enemies, and must be exterminated or driven from the state if necessary for the public peace.
The order authorized violent force in removing Mormons from the state, and thousands were driven from their homes in the middle of a harsh winter. The Extermination Order, and the violence that surrounded it, have left a mark on the physical and cultural descendants of those settlers, of which I am one. We have movies about that time. It's enshrined in our hymns. We discuss it in Sunday School classes. The violence against our ancestors is part of our cultural heritage, even though it's no longer part of our day-to-day reality.

If the Mormon settlers had access to social media at the time, they might have posted about how they were being driven out by the militia. They might have shared how they were American citizens being attacked by the forces of their own state, how people were dying at Haun's Mill and being kicked out of their lawful homes. Perhaps they might have come up with a hashtag as the deaths mounted: #MormonLivesMatter.

And perhaps some long-time Missouri farmer, observing the posts on his phone far away from the violence, might have replied "It's not just Mormon lives that matter, dude. All Lives Matter."

Of course, he's right. Every life matters. Every life is important. Every life has value. But our farmer friend is missing the point—every life should matter, but not every life was given equal treatment; in the eyes of the state, Mormon lives didn't matter. Mormon lives should be exterminated.

Black Lives Matter. This shouldn't be a radical statement; it should be natural and obvious. But people are still posting that #BlackLivesMatter—because the state still treats them like they don't. A black man in the United States is 2.5x more likely to be killed by police during his lifetime than a white man. Black people repeatedly suffer injury, arrest, and death in situations where white people are let off with a warning. The point of #BlackLivesMatter is to call out this injustice, to call out that black people have repeatedly lost their lives to police brutality in a way that simply does not happen to white people.

Black Lives Matter does not mean that white lives don't matter. 
Stop Killing Mormons doesn't mean Kill the Missourians Instead.
Save the whales doesn't mean nuke the dolphins.

Black Lives Matter is a response to people treating black lives as if they don't matter.

If your response to #BlackLivesMatter is that "All Lives Matter", I'm sure you mean well. Everyone's life does matter. But you are implicitly suggesting that discrimination against blacks is not unique or worthy of note. You are suggesting that if blacks are more likely to be killed by police, it's not notable or interesting. Think of how that sounds. Think of what that means.

So yes. Every life matters. All lives do matter. But when black people organize and fight for their own lives, don't try to silence them. 

Black Lives Matter.

Saturday, March 2, 2019

How to get Civilization 6 turn notifications on your iPhone

The Feb 2019 update to Civilization VI added support for multiplayer "Play by Cloud" games. These are long-running asynchronous games where the save file lives on the cloud and everyone take their turn when it comes up. It's useful to be notified when it's your turn to keep the game moving. Steam has desktop notifications that can help, but it would be great if you could be notified elsewhere too. I'll show you how we can use this to set up notifications to your phone.

The developers also added "Play By Cloud Webhook URL" option in the "Game Options" screen. If you type a URL there, Civ will send a message to that URL every time it is your turn in a game. The message looks something like this:

   "value1": "Utah Friends game",
   "value2": "BJ",
   "value3": "134"

The first value is the name of the multiplayer game. The second value is the name of the player whose turn it is. The third value is the turn number.

Of course, that's only helpful if you have a computer waiting around on the internet for someone to send it messages like that. Luckily, there's a service already doing exactly that!

IFTTT stands for "If this, then that". It's a free web service that lets you connect your apps together. You can do things like "If I post on Facebook, then post it on Twitter" or "If the forecast shows rain, send me an email". In this case, we want "If you receive a Civ VI turn notification, send me a notification." We can build that on IFTTT by using the "Webhooks" trigger and the "Notifications" service.

Building our applet

We'll go through this step-by-step
  • Create an account at IFTTT.com
  • After you're signed in, go to "My Applets"
  • Choose "New Applet". You'll see this:
  • Select "+this" and choose "Webhooks"

  • Select the "Receive a web request" trigger.

  • When asked to give your event a name, choose something like "civ6_turn_notification", and click "Create trigger"
  • We've determined that our trigger will run whenever a "civ6_turn_notification" web request is received. Now we need to decide what will happen in response. Select "+that".
  • We want to receive a notification on our phone, so we're going to choose the "Notifications" service.

  • There are two options: A basic notification and a rich notification. A basic notification works fine for our needs. 

  • Now we get to decide what our notification will say! We can use the three values Civ is sending in the message to fill in our notification. I used "It's {{Value2}}'s turn in {{Value1}}. (Turn {{Value3}})", but you can use whatever you want.
  • We've now created a trigger and a response, which together are called an "applet". On the last page, you'll be asked to give your applet a name. Enter the name, click "Finish", and we're done with that part!
  • Make sure you've installed the IFTTT app and logged in, so your phone will be connected to IFTTT.

Configuring Civ to send the Webhook

You're almost done! Now we just need to set up Civ 6 to send the message to your new little applet.

You'll need to visit the IFTTT Webhooks settings page to get your account key. You'll see a URL listed there that looks something like this:


You can visit that URL to see an example of how it all works and try it out, but in short, the text in the place of "<some_weird_text_here>" is your webhook key that ties things to your particular account so that you're getting the notifications instead of me. We're going to take that account key and build a webhook URL for Civ. Yours will look like this:


You can see the event name we chose earlier inside the URL. If you used a different event name, you'll need to use that same name here. Take that URL and put it into Civ 6, on the "Game Options" page. It will look something like this:

And now you're done! You can choose whether to be notified every turn or just on your own turn, whatever works best for you.


Wednesday, September 6, 2017

Paid Upgrades in the App Store

App developers are increasingly turning to subscriptions to build a sustainable business model. This is understandable; the economics of a one-time-purchase business model favor short-lived apps and games, but building a high-quality app requires ongoing revenue. However, many consumers are feeling "subscription fatigue". Each subscription may seem reasonable on its own, but subscriptions add up quickly, and nobody wants to be spending $100/month on app subscriptions.

For years, developers have been asking Apple to support paid upgrades in their app stores. That hasn't happened yet, but I want to make the argument that Apple doesn't really need to do anything; developers can already implement paid upgrades today in the App Store, with just a little bit of extra work. In fact, I'll argue that we can do it better now than what we'd get if Apple added an explicit "paid update" option that required users to pay before updating their app.

We generally all know what a paid update model looks like. Just to be clear, though, this is what I mean by paid updates:
  • Full access to all features when purchasing
  • No separate in-app purchases required upon initial purchase
  • Users can choose to upgrade to new versions on their own schedule
  • Users can choose to skip an upgrade
  • Developers can provide a discounted upgrade price to existing owners of the app
This mirrors the common software business model before the iPhone. If you bought Acme Office 2007, you had immediate access to everything in the app; no unlocking needed. When Acme Office 2010 came out, you could upgrade if you wanted and get all the new features, or you could skip it, and maybe buy the 2012 edition instead.

Paid upgrades aren't right for every app; in some cases a one-time purchase is the right solution, and in others a subscription may be make more sense. But having paid upgrades as an option helps everyone.

The Design

So how are we going to design this? Instead of having separate apps in the App Store, we're going to implement this all within a single app. However, various features of the app may be unavailable to some users.

When we release version 1.0 of our app, everyone who purchases the app will have full access to all of its features. We'll call that feature set A. They paid for those features, after all. Hooray!

Version 2.0 brings with it new features, feature set B. We're implementing paid upgrades here, so a non-consumable in-app purchase is available for our existing users to get access to the new set of features. However, new users who purchase the app at this point are buying the app with the 2.0 features included, so we immediately unlock all features, both A and B, for new users.

Version 3.0 adds additional features. Again, anyone who purchases the app for the first time will have all features available, A, B, and C. They bought the app as it stands right now, and those are the features they get. Users with earlier feature packs can choose to upgrade to the 3.0 feature pack via in-app purchase, which includes all features from all versions.

This is a critical point: Users do not have to purchase every update along the way. If a user bought version 1 and doesn't feel a need for the additional features in version 2, they don't have to upgrade. Later, when they update to version 3.0, they decide they want feature set C, so they buy the in-app upgrade. When they do, they get B as well, so they have A, B, and C. Users are not buying feature sets individually; they're simply choosing when to upgrade to the latest version. It is not possible for a user to have A and C, but not B. There's a linear progression to the features.

Providing a linear feature history makes things simpler for developers as well. Instead of testing 2n combinations of feature sets, there are just N configurations to test; one for each feature release.

Note that I've phrased everything in terms of additional features. Bug fixes would be released as part of the app and would generally be released to all users, whether or not they've upgraded to the current feature set. It would be silly for a developer to fix a bug but lock the fix behind an in-app purchase. So everyone gets bug fixes, and even your users that still just have feature set A still feel like they're getting support from the developer. This actually works better than requiring users to pay for an app update; developers can roll out bug fixes to users on old "feature versions" of the app without having to build separate hotfix builds for each release.

The key feature of this scheme is that users who purchase the app new immediately have access to all features. This enables users to charge a fair price up front.

How do we implement this?

The app store receipt included with every app purchase includes the original_application_version and original_purchase_date fields. These fields can be used to determine what the base feature set should be for a given user. If the original_application_version is 2.0, for example, then we know that all 2.0 features should be available for this user, but the 3.0+ features will require an in-app purchase.

The app store receipt also includes information about in-app purchases. Simply scan the receipt for the highest level of in-app purchase and you'll know what features to unlock. Everything we need is already available in the app store receipt!

We can adjust the pricing of the in-app purchase products independently of the app store price, which allows us to provide upgrade pricing to our existing users.

Will this work for my app?

This systems works well for any app that primarily adds value by adding new features. Productivity apps and professional apps are a particularly good fit. It's probably not a good fit for most games.

Any caveats I should know about?

Unfortunately, yes: Family Sharing throws things off a bit. If I purchase an app at version 1.0 and my wife downloads it for the first time (via Family Sharing) at version 2.0, what feature level should she expect? You could make a reasonable argument for both 1.0 and 2.0, and Apple hasn't documented which one we should expect. It doesn't matter, though, because the actually answer is "neither". In my testing, Family Sharing receipts had a purchase date corresponding to the most recent release (3.0) of the app, even if the family member downloaded the app years ago. I've filed Radar #33076385 regarding this issue, but I'm not aware of any workaround right now.

I know that's a heavy caveat, but it's one that Apple can (and should fix). If this kind of business model interests you, I'd encourage you to file your own bugs with Apple requesting a fix.

And if you do try this out, please let me know! You can find me @bjhomer on Twitter.

Wednesday, June 29, 2016

A U.S. analogy of the Brexit situation

Confused about the "Brexit" situation? Here's how it might go down if the United States were actually the United Kingdom.

The Tea Party hates being part of the European Union because they have to pay a bunch of money, the EU gets to make some laws that affect the US, and immigrants can come in from anywhere in the EU with very few restrictions. They've been complaining about it for years. Finally, Prime Minister Paul Ryan agrees to schedule a non-binding national vote on whether they should leave, figuring it will fail and the Tea Party will have to stop talking about it.

So Sarah Palin goes about campaigning on how terrible the EU is, and how all the money we send to the EU could go toward education instead! $350 million every week to education! Wouldn't that be awesome? And by the way, look at all these immigrants coming in and making it harder for you to get jobs. Isn't that terrible? "Take Back Control" is their slogan.

Paul Ryan recognizes that leaving would be a terrible blow to the economy, so he's encouraging everyone to Remain. The Republican party leadership runs campaigns like "Brits Don't Quit" and stuff, which are fine and all, but it's not as inspiring or scaremongery as "Take Back Control", so the Leave campaign is picking up quite a bit of steam.

This is a national vote, not just a Republican vote, so the Democrats need to be involved too. They're in favor of staying, generally… except that it turns out Nancy Pelosi (the leader of the Democrats in our little story) privately actually has never liked the EU all that much, and would kinda be okay with leaving. So she puts some token effort into supporting the Remain campaign, but doesn't put much effort into it.

Paul Ryan recognizes that they're going to need the Democrat vote on the Remain side if they're going to win. The general leadership of both parties is on the Remain side, so it seems like the one time that they might actually agree on something! But… no. Nancy Pelosi flat out refuses to be seen cooperating with Paul Ryan. Democrats are getting mixed messages. Polls are predicting a narrow win for Remain, but it's a close thing.

The week before the vote, a Democrat senator from Pennsylvania named Jo Cox is shot and killed outside a library where she was about to hold a town hall meeting. She was a supporter of the Remain movement. The shooter was known to be affiliated with far-right extremist groups, and Cox's "Remain" stance and her support for immigration is suspected as a motive for the shooting.

The day of the vote comes, and in a 52%-48% split, Leave wins. Soon, there are reports of Leave supporters harassing and assaulting foreigners across Britain, telling them to get out of the country where "they are not wanted".

Paul Ryan says that he won't be the one to lead the US out of the EU, and announces his upcoming resignation. In the meantime, he's in no hurry to formally notify the EU of any departure. Reporters ask him "what's the plan for exiting the EU?" and he says "Not my problem."

Sarah Palin didn't actually expect the Leave campaign to win; she was mostly looking to score political points. Now the rubber hits the road, and she has to admit that immigration is still going to happen and there's *definitely* not $350 million actually available to go toward education. Leave voters are *super* upset with her. The Dollar starts falling dramatically in value. Sarah Palin announces that after this long and tiring campaign, she's going to take a month off from public appearances, and generally doesn't want to admit that she has no idea how an exit from the EU would actually work.

Democrats are furious with Nancy Pelosi over her weak support of the Remain movement. They produce a 172-40 vote of no confidence in her leadership, and much of the other party leadership resigns too. Pelosi vows to stay in power since the no confidence vote is non-binding, but everyone assumes she'll be gone before long, and there's a lot of questions over who will replace her.

Texas voted heavily in favor of Remain. The governer of Texas says that if the US is going to leave the EU, maybe Texas will secede from the Union and join the EU on its own.

Rumors start spreading that many people were confused about what the vote actually meant (even though the ballot was pretty dang clear), and soon there are millions of signatures on a petition for a re-vote.

So at this point:

  • The leader of the Republicans (Paul Ryan) has stepped down.
  • His presumptive replacement (Sarah Palin) is in hiding.
  • The leader of the Democrats (Nancy Pelosi) is likely to be ousted.
  • Texas is threatening to secede.
  • Nobody wants to actually be the one to notify the EU of the US departure, as it's probably political suicide.
  • Nobody's sure whether the US is staying or leaving, but everyone's unhappy with the situation.

Got it?


Paul Ryan as David Cameron
Sarah Palin as Boris Johnson
Nancy Pelosi as Jeremy Corbyn
Tea Party as UKIP
"$350m to Education" as "£350m to the NHS"
Texas as Scotland

Thanks for reading. If I've messed something up, please let me know!

Tuesday, June 7, 2016

Swift Protocols constrained to a specific class

Update: As of Swift 4, this is supported natively. Just do this:

var controller: UIViewController & MyProtocol

That's it!

Objective-C developers learning Swift often wonder how to represent something like UIViewController<MyProtocol>. The simple answer is that there's currently no way to directly represent that construct in Swift as of Swift 2.2. However, it's possible to work around it fairly easily with just a tiny bit of extra code.

protocol KitchenHelper: class {
    // The normal protocol stuff here
    func bakeCookies()
    func eatCake()

    // The new stuff
    var asViewController: UIViewController { get }

We've added an additional constraint to the protocol; any object that implements KitchenHelper must be able to return a UIViewController as well. Presumably, any conforming view controller would want to simply return self, so lets make that easier:

extension KitchenHelper where Self: UIViewController {
    // Let's provide a default implementation for view controllers
    var asViewController: UIViewController { return self }

Now any view controller class that conforms to KitchenHelper will automatically implement asViewController as well!

class MyViewController: UIViewController, KitchenHelper {
    func bakeCookies() {
        // sugar, flour, eggs...

    func eatCake() {
        // yum

    // 'asViewController' was automatically implemented!

func test() {
    let helper: KitchenHelper = MyViewController()
    let frame = helper.asViewController.view.frame
    print("helper's view's frame:", frame)

Sunday, June 14, 2015

Thoughts on WWDC 2015

In my mind, these are biggest developer-facing announcements to come out of WWDC 2015:
  • iPad Multitasking
  • UI Testing and Code Coverage in Xcode 7
  • Swift 2
  • Swift as an Open-Source language
  • App Thinning
  • Watch OS 2.0 with on-device apps
  • CloudKit Web Services
  • Free iOS provisioning
Note that these aren't changes in the SDK itself. Developers don't have to write a lot of code to get these benefits. iPad multitasking already works if you followed the adaptivity guidance for iOS 8 from last year; support is as simple as recompiling. UI Testing works on your existing apps. On-watch WatchKit extensions use the same SDK that on-phone extensions used (albeit with additional capabilities exposed). You don't need to make any changes to your CloudKit usage in order to enable web services. All these features come essentially free for the developer.

There are, of course, some nice SDK changes as well. UIStackView and NSCollectionView are very welcome additions to their respective platforms, but even these aren't really new; they're just parity features between the platforms. The various new extension points are nice, and the new gaming frameworks are probably a big deal for game developers. But as I see it, WWDC doesn't fundamentally change the kinds of apps I can write.

The focus this year isn't on enabling new kinds of apps, but rather on improving the experience of the apps we can already build. App testing, delivery, performance, and consumption are all improved across the board, with little effort needed from developers. iOS 9 and OS X El Capitan offer significant improvements to the user experience, and Xcode 7 improves the developer experience, but the improvements are largely outside the SDK. The big news from WWDC 2015 isn't about new frameworks, classes, and methods—it's about an improved experience for users and developers.

Caveat: If you're a game developer, GameplayKit, ReplayKit, and the expanded Metal announcements may have made this a big year for you. I'm not a game developer, so they don't really affect me from a development standpoint. But I acknowledge that they definitely look cool, and are definitely part of the SDK.

Saturday, May 2, 2015

Defining Modules for Static Libraries


I figured out how to define modules for static libraries, so you can import them into Swift or into other module-defining frameworks. This solves a common build error: "include of non-modular header inside framework module", as it allows you to turn that non-modular header into a modular one.

You just have to define a custom module.modulemap file and copy it into the right place. Read more for details, or skip to the end if you just want to know what to do.

A brief and incomplete rationale for modules

In 2013, Xcode 5 was released with support for modules, a new way of using libraries and frameworks. Xcode 5 only supported modules in system libraries, but Xcode 6 extended support to third-party libraries as well. Before the advent of modules, developers gained access to libraries via #import statements, which literally copy the requested header files into the importing file. This made the library APIs visible within that file, but required repeatedly parsing system headers again and again as multiple files imported the same headers. This is an unnecessary duplication of work.

We could greatly improve build times if the compiler could parse all the headers of a library just once. However, this is difficult in a #import-based system, because the compiler does not know what files constitute the canonical headers for any given library. Some libraries provide an "umbrella" header that imports all of its API, but the compiler can't always know what header that would be, and even these aren't always complete. (Example: UIKit.h does not import UIGestureRecognizerSubclass.h.) We needed a better way of defining the canonical interface for a given library.

Modules are that better way. A module is a binary representation of a library's interface—once built, the module can be reused throughout the entire compilation process. It can also be used to provide access to the library from other languages, such as Swift. In fact, Swift code can only make use of frameworks and libraries that have a module defined, so this becomes a critical piece of infrastructure going forward.

Module maps

So how do we define a module from a bunch of headers? How do we define the canonical API for a library? Module maps. A module map is a simple file that defines the canonical headers for a library. They're easiest to understand by example, so let's jump right in.

The following is a valid module map for an imaginary library. It is place in a file named module.modulemap in the same directory as the library headers.

module AirplaneKit {
   header "Airplane.h"
   header "AirplaneView.h"
   header "Cockpit.h"
   header "Fuselage.h"
   header "Wheels.h"
   header "Wings.h"

Simple enough; the module map is just a list of headers that define the representation of the library. It can get a bit tedious to write out every header, though, and it's easy to forget to update the modulemap when you add a new header, so module maps support a convenient syntax:

module AirplaneKit {
   umbrella header "AirplaneKit.h"
   export *

That export * line means "Also consider any file imported by one of the listed headers to be part of the module." This is generally what you'll want to do. (The umbrella part is not strictly necessary, but indicates that the header is expected to import every header file in its directory.)

In general, Xcode has fairly good support for defining modules based on your own frameworks: just set the Defines Module build setting to YES and maintain your framework's umbrella header. Xcode will build the appropriate module map file and embed it within your framework. Support for static libraries, though, is somewhat lacking.

Before we move on, one important note: In Xcode 6.3.1, you must clean your project after any change to a module.modulemap file. In my experience, the compiled version of the module is not rebuilt when the module map file changes. Also, when tweaking the module map file, make sure you're editing your original file, not the one in the build folder. Xcode sometimes likes to jump to that one instead.

Defining modules for static libraries

If you're using a static library and you want to make it available to Swift or to another module, there are 2 things you need to do to "modularize" it.

1. Add a file named exactly module.modulemap as described above.

2a. If you're using someone else's library you didn't write, you probably already put the headers somewhere. Just write a module map file for the library and put it with the headers.

2b. If you're building your own static library, make sure your library's headers and the module map are being copied to [build directory]/include/[LibraryName]/. If your static library target is using a Copy Headers build step (as is the default in Xcode 6.3.1), remove it. Instead add a Copy Files build phase, configured as follows:

That's it. Really. After doing the above, you can now use your library from Swift. You can read more about modules and the modulemap format in the Clang Documentation.

If you have any problems, please let me know on Twitter (@bjhomer). I'd like to make sure these steps work for everyone.