How Blither uses the coordinator pattern and SwiftUI together

I never have enough time to work on the games that I make. So when I am working on them, I want to stay focused on the game screen, and spend as little time as possible writing the other boring (but still necessary!) screens for the App. Apple’s SwiftUI framework is very easy to use, and if you don’t much care about making things pixel-perfect, it can sure save a lot of time.

I am not yet convinced that SwiftUI is all that great at navigation, however. I feel like I only just got used to coordinators in UIKit (admittedly many years ago now), and maybe I’m still in the honeymoon stage with them or something.

So for my latest game, Blither, and somewhat by extension this open source Hexagon Grid Generator that I released, I’m using SwiftUI for all the straightforward UI, SpriteKit for the “interesting” views (game and grid), and UIKit mostly just for its UIViewControllers.

In Blither, I have a single UINavigationViewController, and a class named AppCoordinator that manages the navigation stack. It looks like this:

public final class AppCoordinator {

    public enum Route: Int {
        case about
        case appIcon
        case back
        case game
        case mainMenu
        case newGameConfig
        case options
        case rules
        case stats
    }

    public let navigationController: UINavigationController = {
        let controller = UINavigationController()
        return controller
    }()

    public func navigate(to route: Route) {
        if let presented = navigationController.presentedViewController {
            presented.dismiss(animated: true)
        }
        switch route {
        case .about:
            let viewController = AboutViewController()
            navigationController.pushViewController(viewController, animated: true)
        case .appIcon:
            let viewController = AppIconSceneViewController()
            navigationController.pushViewController(viewController, animated: true)
        case .back:
            navigationController.popViewController(animated: true)
        case .game:
            if let topVC = navigationController.topViewController, topVC is GameViewController {
                // already showing the GameViewController, so pop first
                navigationController.popViewController(animated: true)
            }
            let gameViewController = GameViewController(coordinator: self)
            navigationController.pushViewController(gameViewController, animated: true)
        case .mainMenu:
            if let topVC = navigationController.topViewController, topVC is MenuViewController {
                return // already showing the MenuViewController
            }
            let menuViewController = MenuViewController(coordinator: self)
            navigationController.pushViewController(menuViewController, animated: true)
        case .newGameConfig:
            let configVC = PlayerConfigurationViewController(coordinator: self)
            navigationController.present(configVC, animated: true)
        case .options:
            let viewController = OptionsViewController(coordinator: self)
            navigationController.pushViewController(viewController, animated: true)
        case .rules:
            let rulesViewController = RulesViewController(coordinator: self)
            navigationController.pushViewController(rulesViewController, animated: true)
        case .stats:
            let viewController = StatsViewController(coordinator: self)
            navigationController.pushViewController(viewController, animated: true)
        }
    }
}

That may look like a lot, but if you look closely, almost every switch case is the same. The AppCoordinator instance is created in the app delegate’s standard didFinishLaunching function:

@main
class AppDelegate: UIResponder, UIApplicationDelegate {

    /// The root coordinator for the app.
    var appCoordinator: AppCoordinator?

    /// The main window
    var window: UIWindow?

    func application(
        _ application: UIApplication,
        didFinishLaunchingWithOptions launchOptions: [UIApplication.LaunchOptionsKey: Any]?
    ) -> Bool {

        let window = UIWindow(frame: UIScreen.main.bounds)

        let appCoordinator = AppCoordinator()
        self.appCoordinator = appCoordinator

        window.rootViewController = appCoordinator.navigationController
        window.makeKeyAndVisible()
        self.window = window

        Blither.setup()

        appCoordinator.navigate(to: .mainMenu)

        return true
    }
}

All of those View Controllers getting created in the AppCoordinator are UIHostingController subclasses, and look almost exactly like this one for the main menu:

public final class MenuViewController: UIHostingController<MenuView> {

    private weak var coordinator: AppCoordinator?

    init(coordinator: AppCoordinator? = nil) {
        self.coordinator = coordinator
        let menuView = MenuView(coordinator: coordinator)
        super.init(rootView: menuView)
    }

    @MainActor required dynamic init?(coder aDecoder: NSCoder) {
        fatalError("init(coder:) has not been implemented")
    }
}

If you’ve worked with SwiftUI and UIKit together before, you’ll recognize the UIHostingController, but even if you haven’t, all you really need to know is that MenuView is a standard SwiftUI View, meaning it’s dramatically fewer lines of code to add something like a button. And because it also holds a reference to the AppCoordinator, the definition for a button can look like this one:

                Button("Read the Rules", action: {
                    coordinator?.navigate(to: .rules)
                })

When that’s tapped, the coordinator pushes the RulesViewController onto the stack.

If I wanted, I could get rid of the coordinator reference, and do something like this:

                Button("Read the Rules", action: {
                    (UIApplication.shared.delegate as? AppDelegate)?
                        .appCoordinator?.navigate(to: .rules)
                })

…but I don’t like how that looks quite as much, and it also closes the door on dependency injection.

Hopefully you can appreciate how simple this all is! I’ve been pretty happy with how easy I found it to create new screens using this framework. Let me know in the comments or over on mastadon if you have done something similar, as I’d love to hear about similar approaches.

Blither for iOS

Last week I launched an app for my board game Blither. I’ve written about Blither on this blog twice previously, the first time describing Blither’s rules and a bit about how and why it was created, and the second time talking more about some basic play strategy. I was particularly proud of Blither as a game when I first designed it, and I am still pretty happy with it.

After launching the app, I spent a bunch of last week improving it in a lot of ways, and I recorded a video introducing the app and showcasing some of those changes on Sunday:

As you can see if you watch the video, I was (and still am) especially excited about the “high score mode” (which I’d only finished coding-up that day).

For now, the app is just $0.99 (USD). I’ve got a long TODO list in the project’s README, but I’ve already said semi-publicly that I’d like to increase the price when I hit certain milestones:

  • I’ll add $1 to the price when I add an actual interactive tutorial (that’s probably next up)
  • another $1 if I can get the AI up to at least “giving me a challenge” level
  • and +$2 if or when I add asynchronous multiplayer (almost certainly via GameCenter again)

I’d also like to add some leaderboards for that “high score mode” I mentioned. We’ll see.

Xcode tips and keyboard shortcuts

I love working in Xcode. It was my first “real” IDE experience, and while I still use vim pretty regularly it’s generally not for editing code (anymore). These days, whenever I’m not working in Xcode (lately it’s almost always Visual Studio on Unity projects), I’m wishing I was.

I read iOS Dev Weekly (https://iosdevweekly.com/) most weeks, and it was via that lovely resource that I discovered this great GitHub page full of Xcode-Tips (https://xcode-tips.github.io/). I already helped include one tip there (about enabling spell-check), and this post is inspired by one of the tips I found there in particular, about using `cmd-shift-j`. 

Xcode is a 3 panel layout. The middle panel where you actually edit code can be split up in a number of ways, (tabs within tabs? c’mon), but I won’t go into that in this post.

The left panel is called the “Navigator”. It has tabs across the top and defaults to the first tab, or “Project Navigator”, showing all the files in your project hierarchy. 

  • Filesystem tip/aside: When I first started using Xcode I was surprised to learn that files presented here are not necessarily 1-to-1 with the files on the filesystem. On one of my current projects, we are using the awesome open source XcodeGen (https://github.com/yonaskolb/XcodeGen) to generate the project from files on the filesystem. It’s actually called from a script that we run from a git checkout-hook, so we almost never have to think about it. This was a new-to-me workflow, but has a lot of benefits, including keeping the project files consistent with the filesystem!

Keyboard shortcuts relevant to the navigator:

  • Hide (or show) the whole Navigator pane with `cmd-0`. (That’s a zero.)
  • Jump to any of the tabs in the navigator with `cmd-<number>` where number is the index of the tab. So `cmd-1` opens the Project Navigator. This works even when the Navigator is hidden!
  • Best of all, the aforementioned `cmd-shift-j` will open the Project Navigator and select the file you are currently editing. You can then use the up or down arrows to browse different files, and `cmd-j` and then `enter` to return to the code editor.

The panel on the right side of Xcode is the Inspector. It too has tabs, and what’s great is that the keyboard shortcuts are very similar to the ones for the Navigator, but with the addition of alt:

  • Show/Hide the Inspector with `cmd-alt-0`.
  • You can also jump to one of the tabs with `cmd-alt-<number>`, again, where number is the index of the tab. What’s interesting here is that there are a different number of tabs here if you are editing an interface builder file. (I don’t think I’ve ever used these shortcuts.)

In general, I am far more likely to want to hide the Inspector pane than the Navigator pane, so it’s kind of a shame the shortcuts to show/hide them aren’t reversed (not to mention the fact that cmd-alt is a difficult combination on my Moonlander keyboard, but of course I could fix that).

I wrote this up in part so I can create another PR and reference myself as the source for a tip about showing and hiding these panes, but this post was also inspired by sharing with another member of my team that I do the majority of my development on a MacBook, without external monitor. <insert scream emoji> One of the aspects that makes that experience tolerable are all these keyboard shortcuts that let you maximize the space you’re using to edit code quickly and easily.

I hope you learned something from this, but if you didn’t, go check out that Xcode-Tips site, because you’re sure to learn something there!

why I prefer not to teach kids visual scripting

I’m actually pretty adamantly biased against visual programming (sometimes referred to as block-based coding, or visual scripting). I’ll elaborate.

First, it’s important that you understand visual programming to be generally more limited in scope and capability than most (though certainly not all) text-based computer programming environments. Most block-based coding frameworks are written “on top of” some other coding environment, and will have only as many features as the programmers of them have bothered to (or had a budget to) implement as a subset of those features and capabilities of the original environment. But it’s also worth noting that the original APIs they are coding on top of will probably be changing as fast (or likely faster) than they have time to implement in the block-based equivalent. So even if the desire is for 1-to-1 feature parity, they will likely always be a subset. (Worth noting that as far as I know, no block-based coding environment has been written in a block based language, they are all coded in some other text-based language environment.)

So why is it bad that it’s limited? This is just for teaching right? Well, my argument is mainly that I believe we tend to prefer to do things the way we first learn to do them**. It seems like most proponents of block-based coding are in education, but I don’t think that the folks teaching it, while they are obviously well-intentioned, realize that there are a limited number of practical applications of block-based coding.

Obviously context matters here. If you are teaching a specific tool that exists for a specific purpose to someone who only wants to be able to do that thing, then maybe that’s fine. I’m mostly opposed to teaching kids (or more even adults) more generally the concepts of coding by teaching them those concepts using visual-coding or block-based coding.

I think it goes like this: if you are presented with the choice of teaching a kid to drag some cool looking blocks around a screen versus getting them to type some (possibly esoteric) syntax into a text editor, then drag and drop seems like the obvious choice! And I can even see an argument that teaching coding concepts, it might seem like decoupling them from a programming-language specific syntax seems like a good idea… but I think most people, when moving beyond learning the initial concepts, are going to prefer to do it the way they first learned it. And that’s where the problem comes in! if the way they first learned to code was with blocks, they’re going to be used to (and possibly prefer!) a fairly limited way of coding.

Code is text. Text is code. “visual coding” is putting a graphic design on top of text. You might argue that all programming languages are built on top of other programming languages, and that’s true, and I’m certainly not arguing everyone should learn assembly before they learn C. But I will argue that you should learn Python before you learn a VPL.

As an aside, I struggled to find a good metaphor for this article. The closest I got was this: It’s sort of like communicating with Emoji. You can definitely get some meanings across, but if you are going to be nuanced about it, or have something very specific you need to communicate, it’s definitely not going to be good enough. But if you never learned to spell, and only learned emoji, you would be at a serious communication disadvantage. This metaphor breaks down pretty quickly though.

**BTW, if it turns out you have (or know about) evidence that I am wrong about this basic premise, I’d love to hear about it. It fits with my understanding of human behavior, but I’m certainly no expert on human psychology!

iOS Updates and version numbers

First of all, the update to Catchup I mentioned a while back is finally live in the app store today! This got hung up a bit because Nick wanted me to make the new catchup rule the default. I told him I would definitely do this if he would handle translations of the rules update. (But of course wrangling a bunch of translators is much more difficult than the few lines of C++ needed to make the rule change itself!) So as of this writing, the rules change is still optional (and off by default). If and/or when we get some translated rules, I’ll probably push out another update to flip the default.

I’m also working on updates to some of my other apps. Unfortunately, it’s not really a straight-forward process, and there are some that will still probably not get an update at all. (Action Chess, for instance, just needs to be entirely re-written, which I’ve pretty much decided I’ll just do in Unity rather than go for iOS native.)

But in all the apps I’ve done so far, one thing I’ve had to do is change the code that shows the version number. I thought I’d write a mini-tutorial because this is kinda dumb. In pretty much all my apps, I previously had this block of code somewhere (usually in an AboutViewController class’s ViewDidLoad or ViewWillAppear method):

[self.versionLabel setText:[NSString stringWithFormat:@"v%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]];

…but now I’ve changed it to the following:

[self.versionLabel setText:[NSString stringWithFormat:@"v%@.b%@", [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleShortVersionString"], [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"]]];

This results in a version number that looks something like v1.4.b2.

(It’s worth noting that I highly recommend putting a user-facing build number in your all your apps somewhere. This is super important for getting bug reports and feedback. The technique above allows your code to update that user-facing number without having to include it in your code directly.)

In case it’s not clear, self.versionLabel is a UILabel instance, either initialized in code elsewhere, or (more likely) in a Xib or StoryBoard.

Anyway, Apple put out a technical note about version numbers and build numbers back in 2015, but somehow I missed it. Now I’m not 100% sure about this (possible it’s just that I was always confused about this), but my theory is that, at some point (maybe around 2015), the CFBundleVersion key changed functionality, from the version number to build number, and the CFBundleShortVersionString was introduced as the new version number. (This is really difficult to google for, I tried, so if anyone has a more accurate historical rundown, I’d be interested in hearing it.) Anyway, both string are required, but the build number is specific to the version number. (I.E. both have to increment for actual releases, but if you bump the version, you can reset build number back to 0 or 1, or whatever.)

These values are changed in Xcode, in the general project settings. Worth noting that the version number is shown to the user in the app store, but I don’t think build number is exposed anywhere (that I’ve seen). I usually try to follow semantic versioning, with the actual version number containing the first two dots (major and minor version changes), and more or less use the build number as the third “patch” number.

I guess the thing I find the weirdest about these bundle keys is that neither one is named “build”. And I would expect the build number to be the shorter one, not the version number. But maybe that’s just me! Hope this helps someone.

Protocols all the way down

As a programmer, one of the things I like to argue against is the concept of “magic code”, code that works because of some unseen bit of code elsewhere. In iOS, the principal is exemplified by “magic” methods you can include in various subclasses that do rather important things. Want to handle touches in your UIView? Just implement the method touchesBegan:withEvent:, touchesMoved:withEvent:, touchesEnded:withEvent:, and touchesCanceled:withEvent:, and you’re good to go. Want to set up your UIViewController‘s visual layout? Make sure you do so in the layoutSubviews method.

But how do you know about all these magic methods? This is definitely one of the questions that I found the most difficult when I first began iOS development. Learning about all this magic is basically the same thing as learning iOS development. Knowing Apple’s APIs is how you develop iOS apps. Knowing their quirks is how you get to be an expert.

But if you’re just starting out, it’s important to know that most of these magic methods are (generally, not always, but generally) defined in a protocol. When an object conforms to a protocol, it basically says that it (or one of its subclasses) will implement some set of methods. Want to know what protocols UIViewController conforms to? In Objective-C, you would simply open up its header and check it out. (Of course, a protocol might be defined even further up the chain, in one of the headers for a class the view controller inherits from.)

But how do you figure out what protocols a class conforms to in Swift? As near as I can tell, the only way is to open up Apple’s documentation. This seems like it would not be enough, since you might be working with a non-apple framework, or worse… it is possible (gasp) for Apple’s documentation to be spotty or outright incorrect. (I’ve done a few google searches, and read about 20 tutorials and blog posts, and I still don’t know how to figure this out from code alone, so I’m really asking this question. I’ve also started a stack overflow question on the topic.)

I don’t want this to be a “I think Objective-C is superior to Swift” post, but I do think there are legitimate reasons for header files, and this is one of them. Once you get beyond a certain level of iOS proficiency, poking around in those header files is akin to using the “view source” as an intermediate web developer. It’s one of the ways you learn how other people approach a problem.

Sharpening the Yak

Mixed Metaphors

The title of this blog post is a mixed metaphor. It’s a mashup of two common programmer idioms, sharpening the axe, and shaving the yak. I’ve been doing both this week, but before I get into that, I’ll define the terms.

Sharpening the Axe actually comes from a quote attributed to Abraham Lincoln: “Give me six hours to chop down a tree and I will spend the first four sharpening the axe.” When googling around for how this applies to programming, it seems a lot of folks have (for some unfathomable reason) latched onto the phrase “sharpening the saw” instead. I can think of four general categories of specific activities this could mean:

  • direct study — Ie., reading a book on a language or API, or reading and/or studying some relevant source code. Anything that directly applies to some programming task you have to undertake.
  • indirect study — This could include reading more generally about programming or related “industry” news, or learning a new language you will not immediately be using, or any other research not directly related to your current task list but (hopefully) teaching you something tangentially related.
  • architecting — This could be formal, in that you’re writing a document or outline, or putting together a task list, or just more generally thinking about the task(s) you have at hand. (I find I do my best architecting in the shower.)
  • practice — Writing code, but not code you will be using. I’m not much for this one, but I’ve heard a lot of good programmers say they write something once, throw it away, then write it for real. That sounds like a lot of extra work to me, but who knows, it is definitely easier to write something the second time. I’m not sure it’s guaranteed to be better though.

Yak Shaving is a more complex and subtle problem. Jeremy H Brown defined it in a usenet post in 2000 as “what you are doing when you’re doing some stupid, fiddly little task that bears no obvious relationship to what you’re supposed to be working on, but yet a chain of twelve causal relations links what you’re doing to the original meta-task.” The programmers Stack Exchange has more on the definition and history of the term yak shaving.

So what have I been doing this week?

I’m working on iCloud syncing for ActionGo, my next game for Apple TV and iOS. In a way, this is already shaving the yak, since I’m really only working on that because the Apple TV doesn’t support filesystem saving, and iCloud is their recommended solution. But after only a day or so of work, I found out that it does support NSUserDefaults key/value saving. (Up to 600 K, plenty for a saved game or two.) Since I’d already planned on implementing iCloud as key/value, so long story short, now I’m doing both. (Which is of course better, because it’ll work offline too, just without the syncing.)

But I’ve never done iCloud syncing before. *queue sharpening sounds* There are at least a couple of ways you can store data there, key/value, or document-based. Key/Value is definitely preferred for my use-case (a bit of state data for games in progress, and storing overall meta-game statistics), so I focused on that, but even then there are a bunch of different ways to go about it. Consensus seems to be that it’s really easy to get working, but almost all the blog posts and resource sites I read focused on that initial experience and I didn’t end up finding anyone who went into best practices.

So here’s the yak shaving rabbit hole (oooh, a third metaphor?): I’m using Generic Game Model for game state, which already had saving implemented on iOS using the built-in saving functionality that BaseModel provides. But it turns out that I was using an old version of BaseModel, so I had to update that. Then I wasn’t happy with how BaseModel implements its NSUserDefaults storage, so I re-wrote that. Then I wrote a wrapper that handles the syncing to iCloud whenever a key is added to NSUserDefaults (storing an associated NSDate value also, so I can just keep whatever’s latest), and only just now I’m finally getting around to testing. (Only I’m not so much, since I’m writing this post right now instead.)

When is your axe too sharp?

While “researching” this post *more sharpening sounds*, I ran into this critique of Axe Sharpening from a java.net blog post back in 2005:

But for me, the big problem with “axe sharpening” is that it’s recursive, in a Xeno’s paradox kinda way … to sharpen the axe, you need a sharpening stone… But to get there, you need to build a dog sled… But to use a dog sled I need snow, so I need to go to town to get a snow cone machine. I grab my trusty yak to help you haul the machine from town. But it’ll be summer before I get to town, and I don’t want the yak to get to hot, so I shave the yak. In mid February, I proudly lead my shining, bald, shivering yak into my quarterly progress review…

Hilarious.

An Introduction to Generic Game Model

Here are my slides from the presentation I gave tonight at the MN Cocoaheads group about my open source 2D game framework, Generic Game Model.

Description
Martin Grider will share and discuss a few classes he re-uses from project to project allowing him to rapidly flush-out 2D games. The classes themselves are not all that notable, as most developers could probably re-create them in an afternoon, but the techniques are particularly suited to rapidly prototyping turn-based games. He’ll discuss some of his favorite rapid prototyping techniques, as well as talk about “juicing” animations in UIKit, (with a bit of quartz core, as well as a bunch of external libraries thrown in for good measure).

Commentary
As you can see, if you looked through the slides, I have already used this code in a rather large number of projects in the last two years. I was surprised myself, to be honest. At least 8 projects use this thing, 3 of which are in the app store.

My first Cocoapod
While prepping for the talk, I also turned the project into a Cocoapod. I had played around with cocoapods once before, only long enough to install it and run pod install on a test project, (a process which is, if anything, too easy!), but actually creating a pod myself was a new experience, and bit more work than I’d expected going into it. Anyway, you can now add pod 'GenericGameModel' to your projects to try it out for yourself.

Thanks to Bob McCune for running the show and letting me speak!