This iOS dev's learning path

man on top brown hill

Goodness me…

I’ll admit without hesitation: code I wrote 6 years ago, wasn’t that great. And over the time since, I slowly started to realise why it wasn’t that great.


Before I get back to the beginning…

If I had suddenly emerged from my fog-of-past unknowingness, perhaps through some explosively revelatory moment of enlightenment, then clearly, I would have made better choices. Who wouldn’t? For me the overall learning process has been gradual, and so then were the fixes.


Fixes upon fixes.


This is my iOS developer learning path so far, and full disclosure, it isn’t a redemption story. You know the ones. Someone vibe-codes an app and now enjoys an average person’s yearly salary each month. That’s definitely not my story. Mine began enthusiastically, with a profound lack of knowledge, about 5 years before I’d even heard of an LLM. No such victory lap here. It’s much more like:

“It was tough. It got tougher, but I think I get it, now. Maybe.”


The ability to make music and videos to go with it

I’ve always wanted that. Mum delights in telling me I’d rock back and forth transfixed by music shows on the tv. Until I inevitably fell-over, and started the process all over again.

Music programming, was obviously a little later in my life. I started taking it seriously in 2018-19. In reality it’s the making of something I first visualised and wanted when I was 10 years old. In many ways, I started making Muser Studio for my childhood self.


“Everybody does have a book in them, but in most cases that’s where it should stay” - Christopher Hitchens (I think)

Sick burn, Chris. Jury is out on whether this applies to other art forms, creative endeavours, or even software development. Only way to truly find out is to commit to trying.


What did I think would be hard? The technical side. Could I loop musical phrases, and have a video with looping sections as a hassle-free outcome? I reasoned that having this result would give me a record of my experimental playing in a way that wouldn’t just disappear into the ether once the strings fell silent. To that end, the extent of my concern was “can I build the machine to do this?”. Whether anyone else wanted said machine barely crossed my mind. I just wanted to know if I could use it to make music.


There are a lot of great tools out there. DAWs, plug-ins, hardware. If you’re reading this, you’ve probably used several of them. My main two struggles with them were:

Faced with a huge blank expanse, do you do your best stuff? Or is it all a bit daunting? Meanwhile, the doodle you did on a napkin has loads of personality and energy to it. That’s what I wanted: a musical napkin, instead of a canvas.


Nobody said “OMG”

There’s a good chance you might relate to this. You have an idea. It seems like a good one. You can’t really be sure. Some people support it, express reservations, or downright call you out on what they perceive to be lunacy. You do your research, but you’re biased anyway, so your reaction to the research tends to have some skew to it. In the end, what you are probably most influenced by is how you feel about your idea. And that can be a wildly vacillating variable.


And so was my daily life. When I shared Muser Studio (or Muser Audio, or Muser Ignite for that matter) nobody went “omg, I’m going to use this for everything.” They were good tools for me. Whether they were good for them was a different question, and at the time I was keen to post-rationalise the answer. Sure, I was disappointed, but I stayed focused, because I had the explanations ready. Either they weren’t music improvisers, or they were so high-end that they already had their process dialled in.


Notice how both explanations let my work off the hook. Were these excuses valid? Possibly. But they were also very convenient, and it may have been an example of being kind to myself in a way that cost me later. Six years on I can’t tell for certain, and that uncertainty is part of this post.


Tools for a room full of people

I’ve spent two decades working in feature film VFX. Amongst other things, I built three sets of tools for Guardians of the Galaxy 2 (supporting fellow Houdini and NUKE artists).


Here’s the thing about that kind of work. Your tools are used by a team, under supervision. So you engineer for the best case, and when someone hits a problem you walk them through it. There’s always somebody in the room.


Meanwhile, software development for the outside world is the opposite. The public isn’t in the room with you, and there’s no sensible way to support them closely. So you engineer for the worst case, because most of the time, nobody is going to walk anyone through anything. Here lies a personal blindspot: I’d been conditioned to build for a captive audience, and hadn’t realised how much that mattered until a lot of wobbly releases clued me in, via the AppStoreConnect dashboard.


Bugs in my pocket

You make your software, you test it thoroughly, and then you hear that “it doesn’t work”. Surely it is user error. You repeat the steps as best you can and you don’t find the issue. Or if you’re lucky you realise the silly thing they were doing and think “well obviously you’re not supposed to do that”.


How do you escape this myopic death-spiral? Fixtures.

What are fixtures?

They are the annoying frenemy that keeps you, or rather your work, on its best behaviour. Test projects you can run your app against, built to be awkward. They are laborious, tedious and boring to make. They are also remarkably helpful for understanding what’s really going on, and building your confidence on what you’re making.

You name them usefully against a note/ticket etc documenting your path to the fix. Make sure to never elevate your fixture to a fixed state. Keep it old, faithfully janky and run your tests against copies of it. That way you won’t risk accidentally “fixing” the fixture, and you’ll always have a record of what didn’t work that one time.


Beyond that, always be on the lookout for ways to be more structured in your testing in general. Obvious stuff to any well trained dev. Not obvious when you’re someone with an impatient drive to make an idea real. Cough, cough me, and possibly you.


An embarrassing one

Back to me clashing with my pre-organised self and his less than ideal code design. And an example of the “best-case” coding habit biting me.


Let’s say you set a tempo before recording. Marking a loop then gives you an obvious grid to quantise to by way of a metronome click. But from the start I knew I wanted a no-tempo approach to work as well. With this you play something, mark a loop, and Muser Studio would rapidly work out the BPM and set the grid instantly, so every later loop can quantise (think timeline snapping) to it. I actually first developed this logic in my VST/AU, Muser Ignite.


I ported this logic to Muser Studio. With a preset BPM this worked great. With an undefined BPM for a freewheeling/freestyle flow, the app would take the first loop just fine, however when it came to your next loop, it would sometimes line it up incorrectly, and you would have no idea why.

a close up of a clock with a red second hand

Fast forward to many head-scratching hours diving through and tracing the logic to narrow down the list of culprits for a crime I hadn’t even fully identified.


Part of it was working out how many bars you’d actually played, which meant making a guess against a reasonable common target. But the sneakier part was the grid itself. It wasn’t bar-wise, it was root length-wise. In freestyle mode, every subsequent loop wanted to quantise to the whole length of that first loop.


Somehow I didn’t realise that was happening for a long time. Quite ridiculous, honestly. It’s also a little funny. I’d built a feature whose entire purpose was removing friction, and the friction hadn’t gone anywhere. I had simply moved it somewhere I couldn’t see it.


Changes

Muser Studio had some really troubled releases, right up until November 2025. Then it got more stable, and thankfully the stability has kept improving since. It’s only since early 2026 that I’ve become properly aggressive about structured testing. Those fixtures and the boring stuff I mentioned earlier.


Also, as I’m sure you’ve noticed, life happens. In August 2025 a major turning point came my way. In trying to navigate that I found it surprisingly therapeutic to focus much more strongly on the things I actually cared about. For me part of that turned out to be this project.


Are you ok?

Ha! Good question. I mean, it’s 1am. Again. Not sure how many days have gone like this recently: staring down the barrel of my past-self’s ill-informed decisions. Then again, it’s very enjoyable to learn, and put that knowledge to use fixing old mistakes. I feel very lucky to even have that opportunity.


In terms of what I’m actually doing, this time it’s the gaps. Muser Studio was designed around marking loops, and looping them. But I want to support better editing and exports, and for that the gaps between loops need an identity of their own. Right now they don’t have one. They’re just the bits between. It seems trivial, but the app wasn’t architected that way, so that lack of comprehensive design has to be addressed now. I’ve written a bit more about the gaps and why they matter for editing.


It’s the same shape as the grid bug. An early assumption, baked in so deep that it isn’t so much a bug to patch, as it is a boundary I hadn’t realised I’d drawn. I designed for loops, not for the space between them.


And that isn’t even the biggest job. That would be the UI redesign. I’ll talk about it another time, but the tl;dr version is that until now I’ve hand-crafted my custom UI, buttons etc, in Houdini, exporting it directly as C++ code (yes, you read that right: VFX software for making buttons, and generating compile-ready .h/.cpp files). It was fun and irrefutably demented, but I’m no match for Apple’s UI design team, so for my next trick I’m starting over with Apple’s SDK components instead.


Knowing when I’m done

So what keeps me going, given it’s tougher now?

I can tell you that it is not “this needs to make money”. Really, I can’t control whether something makes money or not anyway. What I’ve settled on is this: finish what I started. Make the thing that does what I always wanted something to do.


That’s a finish line I can actually cross. And when I’ve crossed it, I can stop, whether it’s making money or not. It is the clear demarcation at which stopping becomes acceptable. Without it, it would always be in the back of my mind that I stopped short of making what I wanted, and I’m not sure I could accept that.


If there’s any peace to be had from dev work where market forces aren’t the guiding compass, for me, it’s this philosophy.


So, an iOS developer learning path?

If you came here looking for an iOS dev learning path, I can’t give you a tidy curriculum. I can share my path though, which has gone more like this:

  1. Build the thing - believing that this is the hard part.
  2. Find out the hard part was somewhere else.
  3. Stop engineering for the best case. Create the boring testing system.
  4. Decide what “done” personally means before anyone else, or any thing, decides it for you.

You have an idea, and hopefully, through all the challenges, you still think it’s a good one. So do I, about mine. But there are two kinds of good. One is good for you: it scratches the problem-solving itch, and it’s the thing you’ve wanted to make for years. The other is good in the eyes of everyone else, and nobody can conclusively tell you that second one in advance.


I’ve simply stopped trying to answer the second question myself. What I can do is decide what finished looks like to me, write it down, and check my work against it. That one has an answer.


Until I get there, I’m fixing things. Toward a finish line that is my own.




Photo credit: Alexander Milo - Man On Top Brown Hill

Photo credit: Meghan Hessler - A Close Up Of A Clock With A Red Second Hand