• 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
  • Local File History for Xcode - My Solution

    “Aaargh. I just lost the changes in that file.”

    Have you ever discarded ALL changes only to find that you really wanted SOME of the changes?

    I have and having just spent a morning restoring a file to its former glory I’ve implemented a solution to help prevent losing my uncommitted changes again.

    You will need Xcode and git installed and you should feel confident with the terminal.

    For my example, I will assume that you have a development folder named “Development” in your user directory. i.e. ~/Development

    Step 1  – create a backup folder

    I’m using ~/DevelopmentBackup as my backup folder in the example.

    Open a Terminal window and enter the following commands:

    > mkdir ~/DevelopmentBackup
    

    Step 2  – copy the files for the first time

    > rsync -r --exclude=.git ~/Development ~/DevelopmentBackup
    

    Step 3  –  initialise the backup

    > cd ~/DevelopmentBackup
    > git init
    > git add -A
    > git commit -m "First backup"
    

    Step 4  – add a run script to your project build phase

    Now we have set up the git repository that we are going to use to store changes, we need to set up Xcode to keep the file changes tracked.

    1. Open your project in Xcode
    2. Select the project in the Navigator pane
    3. Select Build Phases
    4. Add a new Run Script Phase by clicking the “+” button and selecting “New Run Script Phase”
    5. Type the following into the script window:

      NOW=$(date +"%Y-%m-%d_%H%M")
      
      PROJECTS_DIR=$HOME/Documents/Development/Projects
      BACKUPS_DIR=$HOME/Documents/DevelopmentBackup/Projects
      
      rsync -ru --exclude=.git $PROJECTS_DIR/ $BACKUPS_DIR
      
      cd $BACKUPS_DIR
      git add -A
      git commit --allow-empty -m "Backup: $NOW"
      

    Now whenever you build the project, the backup script should run. It works by copying the entire development folder into the backup folder (stripping out the .git files used for your normal source control) and then committing all changes. The good news is that if you keep the Run Script as the final Build Phase, it will only backup successful builds. However, if you want to backup more often you can drag the Run Script up to an earlier phase.

    I have multiple projects in my Development folder so this script backs them all up at the same time. If you have a huge number of projects going at once, you might want to optimise this so you only backup your currently active project.

    You can view changes using “git log” or your preferred git viewer such as Tower or SourceTree.

    This article was originally posted on Medium, January 2nd 2017

    Sunday February 17, 2019
  • I felt too ill to risk working on my BIG project today. But I’ve made something else in my feverish state…

    It’s called Magic 🧽 and is an insane mix of code-completion, auto-correction, and text expansion all with just one hot key press.

    Wednesday February 13, 2019
  • Woke up with an idea for a game at 5AM. Coded it in a day and have now created the icon and submitted to the app store for beta testing. Less than 24 hours! And I think it has potential. But I might be going crazy… I spent quite a bit of time with the usual autolayout punch up too.

    Saturday February 2, 2019
  • I wrote more about why I chose to start using my own term for TCR:

    www.intrepidfrog.com/keepscrap…

    Saturday January 19, 2019
  • Keep/Scrap Development Demo

    FIBONACCI

    Saturday January 19, 2019
  • Xcodeception: I’ve made a Swift Playground that runs in Xcode that launches a task that executes an AppleScript that operates Xcode’s menus.

    Friday January 18, 2019
  • Play, Keep Or Scrap - Developing Without Fear

    In January 2019, I had an epiphany of sorts. I came across a blog post by Kent Beck called test && commit || revert and started looking into what this meant to me. TCR is an idea that blew my mind after trying it out for a day.

    I’ve written about the way I auto-commit every successful build into a special repository in order to ensure I don’t lose work so I was almost there. My test was “does it build” and the commit was automatic if it did. TCR takes this much further but you can see why the idea resonated with me so strongly.

    I had been writing some really tricky code (for me anyway) to do with parsing IMAP responses and I’d written quite a lot of unit tests to test my string tokeniser as some of the responses can get quite complex. I don’t always use TDD but this really needed it so I was already back in that test-first frame of mind when I discovered TCR.

    As an iOS and Mac developer, my primary tool is Xcode which has had Swift Playgrounds for a while but I could never figure out how to use them in my everyday work. After watching this video demonstrating TCR by Kent Beck, I set about trying to make TCR work in a Swift Playground. I ended up writing a couple of command line tools and Keyboard Maestro macros to get it to work.

    I had also agreed to teach programming at my children’s school and was looking at different approaches and tools to use to teach programming. I learnt with BASIC running on an 8-bit processor with no debugger etc… Sometimes that simple world seems so much more approachable than the infinite choices and complexity available today. I wanted a Playground-based approach that was not just toying with Swift but one that I could do serious work with as well.

    To say the least, Xcode and Swift Playgrounds are not really set up to do this yet but with my tools and macros it is workable and I think gives a faster development process than using Xcode’s unit testing framework. I’d long-ago eschewed putting everything into frameworks for a simpler approach inspired by Wil Shipley’s 2005 blog post which meant that I was already in the mindset of managing my source files by sharing them directly (or links to them) rather than packaging them up in frameworks. I had a tool at the back of my mind for a while. Yesterday, I made the first version of it that extracts working code from a Playground and delivers it to the right folders to be integrated into other projects. My motivatioon being my belief that current version control systems are too complex for a solo developer like me and introduce a ton of overhead. I never know what to put in my commit messages and often forget to commit at the right time. As I operate a monolithic repository and flit between projects far too much, I dread to think what my commit history looks like. The truth is that all I care about is that I don’t lose working code and that if I make an improvement somewhere it will be duplicated to everywhere instantly rather than finding out that an API has changed months after I changed it.

    During my research into Playgrounds I came across another video from a talk by Brando Williams on how Kickstarter had made good use of Playgrounds. This reaffirmed that I was on to something by trying to use Swift Playgrounds as a development tool and not just a toy.

    When talking to children and novices, I don’t want to go into the history of TDD and unit tests, explain different git commands, or even go into version control at all. I want to be able to talk about this in a simpler way. I also want to talk to seasoned professional programmers, who know about version control and understand git far more than I ever will, without getting into the details of any particular VCS. Version Control Systems solve a problem that may not exist in the same way if we use TCR and that’s what I want to explore.

    Play, Keep or Scrap is my friendly name for the idea. You can develop in a playful way knowing that you will only keep the working code as anything that doesn’t work is automatically and immediately scrapped. I hope Kent Beck will allow me the indulgence of using my own name whilst I experiment with this. I’ve always found his books and ideas inspiring and was amazed when he replied to an email I sent in the 90s and happy that he also replied to my tweet just this week.

    I’m planning to share my experience in experimenting with Play, Keep or Scrap and the creation of the tools needed to make it a viable software development methodology in the context of making shipping Swift apps and teaching app development to beginners.

    Sunday January 13, 2019
  • Spent another day tweaking my TCR in Swift tools. Expect videos and maybe blog posts next week.

    Saturday January 12, 2019