• Fractal Planning

    A todo app is really simple right?

    The tasks are:

    • Add
    • Delete
    • Mark as done

    We’d all probably be able to make a todo app without any kind of plan but no matter how simple you think something is, it is worthwhile to break it right down into tiny steps that can be confirmed. Only list things that can be independently confirmed and checked off. Anything too vague for someone to check off in seconds needs to be broken down further. I like to start with a user action that is small and easy to test. Then I break that down into mini-milestones that seem stupidly trivial. It takes less time to think this way and we can all use a dopamine hit from checking things off…

    Let’s break this down further:

    • User can add a todo item by entering in it a text field

      • textfield for adding items is displayed
      • user can select textfield
      • user can enter text into textfield
      • user can commit an item to be added by pressing return when editing text
      • added item is shown in updated list
    • User can delete an item from the list

      • user can select an item
      • item shows DELETE affordance
      • user can tap DELETE
      • removed item is no longer displayed in list
    • User can check an item as done

      • items have a checkbox
      • user can tap the checkbox to indicate an item is done
      • done items are show by changing font to strikethrough

    I haven’t even begun to break down the actual displaying of the list in the first place:

    • When user opens the app, a list of todo items is presented below a textfield for adding new items
      • textfield for adding items is displayed
      • list of items is displayed
      • done items are indicated by striking through

    Also, how does the user cancel editing? Can you uncheck a done item? We keep asking questions until we have an answer for everything and a list of things that are precise and small enough to be checked off by almost anybody. You should be able to give the list to anybody and let them loose on the app and come back with a completed checklist.

    You might think this is far too much detail to go into and that it is so obvious that you might as well just write the add() function knowing everything that goes into it. Say we do that and now the ADD task is completed and out of mind. We still had to think through the steps to build it and we still ended up converting the tasks from ideas in our head to lines of code. We might as well write that process down rather than do it in our heads. As Richard Feynman might say unless you can explain how to make the ADD function to a child, you do not understand it fully enough yourself. So make life easy for yourself and keep breaking tasks into smaller tasks until you get to the lines of code.

    Thursday June 8, 2023
  • Make Text Readable Again

    It Was The Best of Times Dickens quote in tiny unredable text.

    I have just completed my 2022.1 update for Readable; an app that I made a few years ago to solve a very specific problem.

    I’m really pleased with the way it has turned out and I’m happy to charge for it now. I hope all those who have purchased or downloaded the free TestFlight version can also see the improvements.

    As a Twitter addict, I spend a lot of my time doom-scrolling as I drink my morning coffee. I wear glasses and as my eyes deteriorate I found that even wearing glasses didn’t help with some things posted on Twitter. I’m of course talking about the cheat of posting screenshots of text in order to overcome Twitter’s character limit. This is all well and good but is not very readable. You have to fuss with pinch to zoom and pan gestures just to read a bit of text.

    One morning, enough was enough and I wondered what I need to do to fix it. I came up with a clever way of processing images that could basically cut out letter glyphs, turn them into sprites that I would then use to reconstruct the words with. With the added facility of being able to “word wrap”. This worked well for many screenshots but was not completely fault-free. But it worked well enough for my personal use.

    Apple have since introduced LiveText scanning that runs an OCR machine learning model on images and does an amazing job of pulling out the text. But the interface is clunky to use if you are just on Twitter wanting to quickly read some posted screenshot of text.

    I got a new iPhone this month for the first time since the 11 and was inspired to refresh Readable. It now uses the ImageAnalyzer Apple uses for LiveText and it works a treat.

    Please give it a try and download it today.

    Saturday September 24, 2022
  • It Started With A Bug

    Don’t track bugs, fix them by Allen Holub caused a stir recently when Holub tweeted about not tracking bugs. What a great idea. In my personal projects I always take the time to clear bugs as I find them. I just don’t want to track a bug list for a hobby!

    But why not at work too?

    It reminded me of the early days of Relentless when we were a small rag tag bunch of game developers who wanted to do things differently. We needed a system to track bugs but we also had a no known bugs policy. I hacked together a Bugzilla server to hold the data. We printed out bugs on a daily basis and fixed them before moving on to features. The novel thing we did was to also keep all the features in the same “bug” database. Essentially, a feature became a bug (as it was unimplemented and was therefore untestable).

    I discovered that if you think of it like this, the app starts as a bug description - app does not exist - so you fix that by creating an executable and move on from there.

    By maintaining a “bug” list in the same system as the feature list, we were able to treat them in exactly the same way. Work was done in priority order and we frequently reviewed the entire database (by printing it out no less) to reprioritise. Bugs were not tolerated and incomplete features were always flagged off when the game was sent to the publisher.

    Friday September 16, 2022
  • My app browsing the Splash git repository. Each commit has a little minimap rendered too. @johnsundell

    Friday January 3, 2020
  • Added a Splash of colour, thanks to @johnsundell. I’ll try to do a PR to add SwiftUITextOutputFormat tomorrow.

    Thursday January 2, 2020
  • More SwiftUI. Git repository browser in the left pane. Text in the right pane. Commit history scrubber at the bottom.

    Thursday January 2, 2020
  • Made a SwiftUI OutlineView to go inside my SwiftUI SplitView. This is going to be quite a complex Mac tool and I’ve enjoyed building the SwiftUI components for it. Lots of polish needed but functionality is getting there.

    Wednesday January 1, 2020
  • Working on a SwiftUI SplitView for a Mac tool I’m developing.

    Wednesday January 1, 2020
  • If you have a Swift or SwiftUI problem like this one from @dev_jac on twitter, let me know and if I have a couple of hours to spare, I will see if I can help.

    Tuesday July 23, 2019
  • SwiftUI - How to Make Columns Without Autolayout

    Julio Carrettoni (@dev_jac) asked how to arrange 2 labels in an H-stack which have the same but minimal width. In UIKit, you would use autolayout constraints to tie the widths together but we do not have that in SwiftUI. We have to think different!

    As each element is responsible for sizing itself, you need to calculate the desired column width before they are rendered and pass that down to the elements so that they can size themselves accordingly.

    Making the columnWidth a state variable means that when the view appears you can calculate the column width and update the state with the new width. This causes a redraw with the correct width.

    Here’s a quick example:

    //
    //  ContentView.swift
    //  Columns
    //
    //  Created by Andrew Eades on 23/07/2019.
    //  Copyright © 2019 Andrew Eades. All rights reserved.
    //
    
    import SwiftUI
    
    struct ContentView: View {
        @State private var columns: [ColumnModel] = [
            ColumnModel(text: "Longer Column"),
            ColumnModel(text: "Shorty")
        ]
        
        @State private var columnWidth: Length = 100
        
        let font = Font.system(.body)
        // need a UI font because I haven't figured out
        // how to get the size of the font yet
        let uiFont = UIFont.boldSystemFont(ofSize: 20)
    
        var body: some View {
            HStack {
                ForEach(columns, id: \.self) { column in
                    Text(column.text)
                        .font(self.font)
                        .frame(minWidth: self.columnWidth, maxWidth: self.columnWidth)
                        .border(Color.black)
                }
            }
            .onAppear(perform: self.calculateColumnWidth)
            .padding()
            .border(Color.blue)
        }
     
        
        private func calculateColumnWidth() {
            let minimumWidth = columns
            .map {
                $0.text.width(usingFont: self.uiFont)
            }
            .reduce(0) {
                max($0, $1)
            }
            
            self.columnWidth = minimumWidth
        
        }
    }
    
    struct ColumnModel: Hashable {
        let text: String
    }
    
    extension String {
        
        func width(usingFont font: UIFont) -> CGFloat {
            
            let size = self.size(withAttributes:[.font: font])
            
            return size.width
        }
    }
    

    Tuesday July 23, 2019
  • The Beta Principle

    For many years in the games industry, I understood alpha to mean “feature complete” and beta to mean “content complete”. This is how we managed projects that involved hitting a GM date with a final disk to ship to retail for a specific marketing window. There was no ability to update the disk in those days and I think we got pretty good at hitting dates set 2 years in advance. We “finalled” in August to hit an October release.

    The world is different today and the meaning of beta has been eroded so much it currently means “broken and unfinished” to many people. As a user, you should not expect anything from a beta. “It’s a beta,” is the refrain if you dare speak out. Well here I am to speak against this doctrine of user-hostility. A beta should be usable. Otherwise it is not testable. The whole point of a beta test is for users to give meaningful feedback. You don’t get feedback if you keep telling them that they shouldn’t expect it to work as advertised. That’s not what a beta is for for heaven’s sake. It is to find out if it does work as advertised outside of your developer labs.

    Defending incomplete broken betas must stop. We must demand more and expect betas to be usable so we can test them properly. Apple released a fantastic new API at WWDC this year and produced a session on it which is now online. But the API was not available until 2 weeks after the session and subsequent API deprecations have already made some sessions out of date. That’s also after the end of WWDC and any possibilty of asking the engineers about the API in the labs.

    This is not how it was intended, I’m 100% certain of that. The Apple engineers that sweated to make the dates, but sadly missed, must be at least as disappointed as me. But if we were stricter about our definition of beta this would not have been released like this and we’d all feel better about it when it hits beta in August instead.

    Thursday July 18, 2019
  • Operations and Timers

    Whilst on the flight from London to WWDC yesterday, I re-watched the excellent Advanced NSOperations session from 2015 by Dave DeLong. Suitably inspired, I wrote a very simple promisey type extension to Operation that implements a then function to create a dependency tree of operations to be executed. Problem is that as operations run in their own threads, I was now starting the Timer inside an operation and it was no longer firing as expected. It’s taken me a while (jetlag) to figure this out but you have to remember that the timer will not get scheduled once the operation has completed. So you have to explicitly tell it which loop to schedule on using RunLoop.main.add(timer, forMode: .common). As a side note: whenever you start going down the path of callback-hell, promises, futures, or Rx (*shivers*), have a watch of Dave DeLong’s session first.

    Sunday June 2, 2019
  • Up at 3AM so not too bad. This week I’m in San José for WWDC 2019. Although, I have not got a ticket so I’ll be mostly hanging around coffee shops hoping to meetup with fellow app developers.

    Sunday June 2, 2019
  • My iMac Pro is not healthy. Kernel keeps panicking. I’m backing up the backups before I raze this to the ground as it happened after I did a huge delete of old Realm files scattered everywhere. I no longer use Realm as I have rolled my own object store which is better.

    Friday April 26, 2019
  • That thing about waiting for the interviewee to send a thank you note before deciding on them is the stupidiest thing. Firstly, it discriminates against autistic people. Secondly, it wastes everyone’s time. Why interview before figuring out whether the victim follows your ridiculous social mores? If you were smart, you could figure that out beforehand in a phone call. Any company that uses this ”technique” should be avoided like the plague in my view.

    Sunday April 7, 2019
  • Fantastic episode of Under the Radar this week. So much inspiration packed into 30 mins. App developers eveywhere should take a listen.

    Friday April 5, 2019
  • The awful Netflix knock sound every time you start the app and auto playing of previews has forced us to cancel.

    Monday April 1, 2019
  • My post about an Apple Games Console is not an April fool BTW. Or is it? No really — it isn’t.

    Monday April 1, 2019
  • Apple Games Console Coming Soon

    Today, we are closer to Apple releasing a purpose built console than we have been for a very long time. Twenty years after the ill-fated collaboration with Bandai that produced the Pippin, Apple have all the right pieces in play.

    Whether or not Apple likes games, they have finally admitted that they are a games company too. They have inadvertently created the biggest mobile gaming platform in the world with iOS, games have their own tab in the App Store, and this autmun/fall there will be an Apple Arcade built into all Apple devices. That screams “console” to me.

    Since Microsoft introduced Xbox LIVE Arcade, Sony and Nintendo have added similar offerings. Exclusive games are a must-have in order to successfully launch a games console today. With Apple Arcade, Apple gets a bare minimum of an exclusive window for all their platforms and I would not be surprisd if we start to see must-have games on this service whilst users are guaranteed a source of games to play whilst saving up for the big titles. No loot-boxes will be a big pull for parents and jaded gamers that are fed up of never having a complete game experience without paying through the nose.

    Apple TV could have been a games console except developers were required to support the Siri Remote which is singularly difficult to adapt games to. I did it with The Trace but it was a challenge to say the least. What stopped the Apple TV from becoming a console was the “TV”.

    If Apple release a new games-focussed Apple TV with beefed up specs, a proper game controller, a games subscription service, and exclusives, at a console price, I would be delighted.

    Monday April 1, 2019
  • Don’t forget to ignore ALL tech and news stories today. Go for a walk or something instead.

    Monday April 1, 2019
  • I’ve shamelssly plugged my intrepifrog.com blog in my tweets too. It’s been fun to go against the prevailing wisdom and get it right. Now back to app development.

    Monday March 25, 2019
  • Apple had me worried for a while. I thought that getting the games subscription wrong meant I would get the no bundle prediction wrong too. Nope. I was right. And I half got the games thing. I’m giving myself a couple of points.

    Monday March 25, 2019
  • Dissenting Opinion

    It’s the eve of the Apple Event, 24th March 2019. Apple have cleared the decks for the big day by announcing updates to iPad, iMac and AirPods on Monday, Tuesday and Wednesday the previous week.

    It seems I’m the only person that has no inside info as every podcast I listen to, including ATP, Stacktrace, Connected, Upgrade, Download, etc, seems to be expecting two things I do not see. It’s obvious that some kind of video streaming service is coming. It’s Show Time after all. But people who I think have a bit of an inside track also think that Apple will be offering a bundle of media services like Music, News, TV, Movies and possibly a games subscription service. Here are my 3 top reasons that Apple will not announce a media content bundle on the 25th March 2019:

    1. Apple Don’t Bundle

    How is that Logic/Final Cut/Filemaker bundle? Remember when Apple offered an iMac, MacBook Pro, iPad, and iPhone at a great bundle price? Nor do I.

    Apple just do not tend to bundle things up. In fact, they like to do the opposite. Just add some RAM onto any base spec Mac to see this in action. Apple spec out for a headline price to advertise and have big margins on add-ons.

    2. Who is Driving Sales?

    The Music execs will claim it is the great music, and the TV execs will claim it is the awesome shows. There is no way that a TV exec is going to allow a music label to have some of their cut. It just does not happen that way. A long time ago, I made a music game for Sony Computer Entertainment and two of the only content owners we could not license anything from were Sony Pictures and Sony’s music publishing labels. We were working for the same company and we could not get a deal. I will eat my hat if Apple have somehow got Music and TV to share. Apple could say that they’ll pay dividends based on listens or views. I would not go there if I were a content company. Content is King – but nobody knows which content until it’s too late. You cannot plan a business based on a content exposure model unless the content is crappy and cheap to produce and you are not making it. See all social media. Apple is reportedly spending significant sums on new shows so they are also competing for eyeballs. Would you do an eyeball-based deal knowing this and knowing how much Apple can spend on content? Nor would I.

    3. News is Worthless

    Controversial opinion maybe but the News app proves out that there is no value in the content there to bundle. The big news players have already set up paywalls or membership schemes. What’s left is the scraps. Also, I’m fed up of being fed the same story derived from the same press release by 10 different outlets as if they are unique stories. The bundling in News works against making it worth keeping on my device, frankly.

    That’s the media bundle debunked. Now for the game subscription service…

    I just do not get who benefits from this. The one possibility is that premium games that would not otherwise be made are now possible. But we have a similar problem in dividing the spoils. Who is driving the sales? A must-have experience that is an hour-long might be bringing more customers in than a 60 hour epic. Why should the hour-long game take less and not more? Who decides this? Another version is that Apple just buys an exclusive period for a game. That could work but it puts Apple in the position where it needs to guarantee subscription content on a regular basis whilst basically taking out all the oxygen for every other premium title so survivability becomes linked to the 1-2 slots you get a month with this model. Casual gamers don’t need any more “free” games and I don’t think gamers have come around to the iPad as a games console idea yet.

    Personally, I would be happy if they just announced season 8 of Game of Thrones available for free on Apple TV tomorrow. I don’t think we’ll get that and I don’t think we’ll get a subscription bundle or a games service either.

    Sunday March 24, 2019
  • I think I’ve broken APFS. Deleting 1,000,000 items and counting.

    Tuesday March 12, 2019
  • So many people thinking Apple will announce a games subscription but I don’t get it. I cannot see why anyone in the games industry would be interested nor why Apple would want to do it. I want high quality premium games for my iPad but not sure this would bring them.

    Thursday March 7, 2019