Xcoders talk: Don't Fear the Project

Last week I gave a talk at our Seattle Xcoders meetup group. The topic was Xcode projects and I discussed the things that make up a project (targets, schemes, etc) and dissected project files themselves a little bit. The meat of the talk was then going through using XcodeGen to generate Xcode projects programmatically so you can stop checking them in to source control. This is a talk I've wanted to give for over a year and I'm glad I finally got around to it.

The really cool thing that happened (which I was not expecting) is the level of questions & discussion after I wrapped up the talk. I've not seen as many questions come out of a talk as this one had. That can generally mean 1 of 2 things. Either 1) I could have done better at explaining things or 2) The topic generated that much genuine interest in people. From what I heard it's more the latter than the former though there are definitely areas that I could have expanded on.

Many of the questions that arose came in the area of using flags for individual files in generated Xcode projects (think of toggling ARC on a per-file basis back in the day). I didn't know if that was possible, since I mainly use the file system to organize my sources and tell XcodeGen to grab files from the correctly organized folders. Turns out it is possible to do fancy things like define custom regexes to include certain files and then apply build phases or compiler flags to those matched sources (documentation). XcodeGen is even more powerful than I thought originally!

Were I to give this talk again at a conference or something I'd probably expand it to include a demo where I take an Xcode project that's already existing and adapt it to use XcodeGen, but for this talk I wanted to avoid live coding. The main reason that I delayed giving the talk at all was because I wanted to build a conversion tool. But in the end when I tried it out it was both harder than I was expecting to be, and I didn't think that building a complicated tool for someone to run once and move on from was a great use of my limited time.

We recorded video for the talk and I'll post a link when it's ready. For now, the slides can be found here.

🔗 Where is Windmill on the iPhone?

Markos Charatzas, writing about the state of his Windmill apps:

More importantly. Apple took the stance that the Command Line Tools Package is only meant to be used by developers in-house and not by 3rd parties to provide support for continuous integration systems - continuous delivery in the case of Windmill.

As developers building things for Apple's platforms we are largely operating within the walls set forth by Apple itself. There could be a whole industry of products built to support making development easier (think of things like Fastlane but easier to use).

Windmill is one such tool that looks really interesting. It currently runs on the Mac and monitors your local git repository for changes, building and running your app to make sure things don't break while you're developing. I've yet to use it personally but more importantly think it's something that should be allowed to exist. Apple should be in the business of fostering creative solutions to lots of different problems instead of shutting them out.

If Apple's stance is that it's okay to build workflows and internal apps on these command line tools, then why is it not okay to try to make a product out of them? It seems to me that forcing every place to deal with these issues individually will waste a lot of time and add tons of friction to workflows that could be eased with these tools.

This is one case where I wish Apple would be more conversational and clear. Markos has commendably been trying to get a conversation started. But oftentimes these "discussions" are one sided, with interested third-party developers being the ones talking and patiently waiting for Apple to respond. I'd love to see that change someday but the change will have to be on Apple's side, not ours.

Reverting SwiftPM for Tools

For the last few months I've been using Swift Package Manager to manage my tooling dependencies for iOS projects. It's a technique that I learned about from Orta Therox and I adopted it in Scorebook and even made an app template that used it too. The advantages were great, namely that I didn't have to manage any version scripts or vendor tools directories. It just worked.

But over the last couple of weeks things started to fall apart a little bit. I downloaded Xcode 11 after releasing my new Scorebook update so that I could start digging in to all the cool stuff iOS 13 had to offer. I also checked my tools to see if they had new versions available (I'm using 2 different tools at the moment – Xcodegen and swift-sh). I went to update them and that's when I got my first error: dependency graph is unresolvable.

I did some digging and what seems to have happened is that my tools have conflicting dependencies. Bummer!

I had some options at this point: 1) figure out what the conflicts were and solve them by forking and opening pull requests on one or both of Xcodegen and swift-sh. 2) Create separate tools modules for each tool. 3) Roll back using SwiftPM for my tooling needs and build scripts to maintain each tool.

#1 would have taken a long time to resolve and didn't seem super worth my while. #2 would have been slightly more tolerable but maintaining that directory structure didn't seem super worthwhile, and would have likely necessitated scripts for each tool anyway. #3 felt like the right choice in the end, and that's what I went with.

The upshot of going the way that I did is that I can always ensure that I'm using a binary version of each tool, and if I come across one that's not written in Swift I can add that to my project with the same amount of effort as a Swift-based one. Using SwiftPM for tooling like this was always kind of a hack. It was meant to manage dependencies of your project and to easily bring in libraries to your codebase.

I'd love for it to work again someday, but for now I'm mostly glad to have gotten over this hurdle so I can move on to more interesting problems like adding Dark Mode to Scorebook.

I pushed the change I made to my iOS template, and if there's a better way to write the bash scripts I'm all ears (I'm sure there is, since I'm a bash noob still). Check out the updated code here.

Scorebook 2.0 Preview

I've been hard at work over the last few months on a big update to Scorebook. It's going to have a whole new interface, work on the iPad, and support the Dynamic Type accessibility feature.

The first thing that is different is the main UI. There's now a tab bar which gives easy views to your gameplays, the games you've played, and the people you've played them with. It's a really nice way to visualize the games you've been playing.

The big driver of the big UI changes was putting Scorebook on the iPad. On the bigger screen you'll get a split view, with a list of things on the left, and a detail view on the right. And with iCloud sync (which is now enabled by default) you'll be able to see your stuff on any device. It's really great.

From Scorebook's initial 1.0 launch until now, I'd been using the Avanir font across the app. I really do like how it looks but the time has come to move to the iOS system font – called San Francisco. The main reason I did this is because I wanted to support users who like the text to be a bigger (or smaller) size than the default. Accessibility is a big deal. Without it, an app is harder to use or even unusable by people who rely on those features.

With all of the work that's gone into the app, and now with being on a whole new device, I've also decided to raise the price to $4.99 USD. I'm not sure what the higher price will do for sales but I'm hopeful that people will see value in the additional work I've put in to Scorebook.

While the release date isn't set yet, I'm in the final phase of the project – screenshots. Apple has so many different devices nowadays that this is actually a really complicated part of making an app (especially as a solo developer). But I'm pleased to say that I expect to wrap the screenshots tonight and submit the app for release later this week.

Scorebook 2.0 will be a free update to all users. If you want to get in at the existing $2.99 price you can buy it on the App Store today.

Introducing the Xcoders Podcast

I've been working with Liz Marley to create a podcast for the Xcoders and we finally got our first episode out the door yesterday! Our hope is to record on a monthly basis and we'll be talking about all things Xcoders-related. As the two of us are primarily Seattle Xcoders that's where our focus will be to start. My hope is to branch out and talk Eastside and Vancouver BC as well!

You can subscribe to the feed directly at https://xcoders.org/podcast.xml. Our submission to iTunes is currently pending and I'll update this post with that link when it gets approved.

If you have any questions, comments, or topics you think we should cover, please do drop us a line at info@seattlexcoders.org

If you're an iOS developer, or want to be an iOS developer, and are interested in being mentored please fill out this form.

I'm partnering with Nic Laughter to start something really cool 🙂

WWDC 2019 Recap

I'm super thankful that I got to travel to San Jose last week for Apple's WWDC conference. Granted, I didn't get a ticket, but I did go to AltConf (which was right next door to the big show). This was my first time being in town for WWDC and it was a blast. I traveled with my buddy Seth and we took in the keynote together, as well as all the podcast recordings we could fit in.

Monday, of course, was Mac Pro Day, Tuesday we got to sit in the balcony for Gruber's interview of Craig and Joz, and Wednesday was RelayFM's Connected. Following the Connected show on Wednesday we hit up the Ritz for James Dempsey and the Breakpoints, which was a great show at a small club.

It really is true that Apple nerds take over the city during WWDC week. There were lots of Xcoders hanging around (particularly at the Fairmont and Cinebar). And we were all buzzing with the releases from Apple. We came in to the week thinking that Catalyst (née Marzipan) would be on the road to taking over the Mac and hoped for a Mac Pro preview. Boy did we get a Mac Pro preview! It looks like an absolute monster of a machine – complete with a monitor that ships without a stand. And Catalyst looks better than anyone had hoped for. But that wasn't the news of the week.

Nope, that belonged to SwiftUI. In one fell swoop and without saying so explicitly, Apple deprecated AppKit and UIKit. We now have our drawing framework that can scale from the little watch to a big screen TV, and an editor that looks unbelievably great. It's like the good parts of Interface Builder (the visual feedback) without the crappy parts of Interface Builder (the xml files). I can't wait to play with it more.

I'm really looking forward to Xcoders this week. We're doing WWDC lightning talks. It's a great opportunity for folks to give a talk under a low pressure situation, and we have 7 talk scheduled with 3 new speakers. I'm slated to give one and decided to do it on Xcode's integration of Swift Package Manager.

Time to start working on the talk!

Tonight I got bested by a home improvement project that tutorials call "easy".

I need to remember when I'm talking about a concept to not call it easy, because the reader may be at a level where it's not easy for them. The last thing I want to do is discourage someone who's trying to learn.

My iOS Project Template

Like many of my fellow iOS developers, I often find myself starting little projects here and there. Also like my fellow iOS developers, I have developed a preferred project structure. This structure has changed quite a bit recently as I've been exposed to a different way of doing things at Lyft. We have a highly modularized codebase and I quite like that methodology. I dipped my toes in the many framework waters in my time at zulily but what we have at Lyft goes well beyond that.

As such in my personal projects I have incorporated additional modularization and automation. My goal with this post is to peel back the curtain a little bit and give you some ideas on how you might be able to use modularization to create clean boundaries between code in your project.

To kick things off, I've published my template code on GitHub.

I really like using commands via a Makefile to run automations, and further from there my aim is to have a project as self-contained as possible. What I mean by that is I don't want to rely on Ruby gems or Python modules managed by a central system on my machine. I freely admit that this is because of my ignorance to how those environments work. There have been great tools built on those platforms. But, like Orta Theroux wrote on the Artsy blog, I agree that it's time to use Swift Package Manager.

It turns out that Swift is a really nice language to write tools in. For me, as one who hasn't fully grasped Ruby or Python for tooling (though I would like to eventually) being able to use Swift to build some automation has been great. And now we can use SwiftPM to manage these dependencies for us. If you look at my Package.swift file you'll see that I'm creating a "dummy" Swift module to get all the power of swift run in the Makefile.

Make is a super old system, and I had never used it prior to joining Lyft. And I gotta say, I love it. It's a great central place to run commands to do work on my project. To add a new module, I run a script by calling make new-module. The script asks for the name of my module and goes about creating some template files and linking it in to my app.

Secret Sauce

To be honest, I've somewhat buried the lede here. If you glance over the .gitignore file you'll see an entry for *.xcodeproj. Yep, I'm ignoring Xcode project files. This is because I'm using a tool called XcodeGen to create my project files using yaml definitions in my repo.

I love this.

I love that I don't have to worry about Xcode project conflicts in git merges (of course on side projects this isn't a big deal for me). I love that I can easily rename my project on disk and it's instantly reflected the next time I generate the project. I love that I can move a group of files around, regenerate, and have my new file group or module instantly.

My modules all live inside of a Modules folder stored at the repo's root. The project.yml file is what drives the structure of the resulting Xcode project. Each module has its own definition file, which helps keep the project definition file slim.

Wrapping Up

I've been working through these pieces for over the past 6 months or so. When I got back in to Scorebook I adapted the structure, and over a couple of other small projects I've started up I've built out the shell that you see in my GitHub project. I hope some parts of it are helpful for you in some way.

As always I love talking about this stuff and am happy to answer any questions you might have. And, if you've got a better way that I'm missing the boat on please let me know. Let's help each other get better 🙂

I want to write more blog posts, but don't have a lot of topics in the queue. If there's something you'd like to hear about I'm all ears. iOS development, Swift, the Vapor framework, Seattle Sports, Batman, Jesus, whatever might make for a good topic.

I'm all ears!