/dev/trouble
Eric Roller's Development Blog

Re-running my unit tests on Xcode 9.4, I got stuck on an uncaught exception without any useful debug messages. All I got in the log was:

[...]
Test Case '-[AppTests.AppScriptTests testScriptFiles]' started.
libc++abi.dylib: terminating with uncaught exception of type NSException

and nothing more!

Certainly, I tried re-writing my Swift do-catch-blocks to be able to catch an NSException (Objective-C), but whichever catch line I added, it was never called.

I also tried stepping though the code in the debugger but since the test commands are read from a separate script, and code is spawned on separate threads, this is rather difficult. After trying for a couple of hours yesterday, I gave up.

Today, I remembered a different trick:

Adding an exception breakpoint.

In Xcode,

  1. open the Breakpoint Navigator (Cmd-8);
  2. scroll to the bottom and click "+";
  3. select "Exception Breakpoint…";
  4. since it was an NSException, I chose Exception: "Objective-C", Break: "On Throw", Action: (none);

With that exception breakpoint active, I could re-run my unit tests. There are quite a few legitimate exception throws in my project. For these, it was just a question of selecting "continue" in debugger until I finally landed on a line that was not meant to crash (the last command shown here):

if let allSelectedIndexPaths = self.tableView.indexPathsForSelectedRows {
    for selectedPath in allSelectedIndexPaths {
        self.tableView.deselectRow(at: selectedPath, animated: true)
    }

    self.tableView.reloadRows(at: [ allSelectedIndexPaths ], with: .automatic)
}

So what is wrong with this code?

Answer: A different thread had removed rows from the table view, resulting in me trying to refresh non-existing rows.

MacOS: Internet Recovery

- Posted in macOS by

Starting off with a replaced internal SSD on a MacBook Air, it doesn’t boot, obviously. It is necessary to boot into “Internet Recovery Mode” by selecting Command-R at startup, or, as I did, Option-Command-R to recover onto High Sierra.

I erase the disk in Disk Utility and select to install macOS High Sierra. After a few seconds I am greeted with the error:

The Recovery Server Could Not Be Contacted

A number of possible solutions are listed on the Mac OS X Blog. I used the first one, except that using sudo was not possible (command not found ?); I ran date in the Terminal which confirmed that the date was wrong, then I updated it using Apple’s time server (without sudo):

% ntpdate -u time.euro.apple.com

The run date once more to check that the date & time has been updated.

Back in the High Sierra installer, I get asked to select a destination Disk, but my internal SSD cannot be selected, because:

This disk doesn’t use the GUID Partition Table Scheme

The solution is to use Disk Utility to erase the drive, but in the High-Sierra version of Disk Utility, I had no such option to select the partitioning scheme!!! The Partition button is disabled.

I eventually solved it by rebooting into the old recovery mode (Command-R) and using Lion’s Disk Utility to reformat the drive, before returning to the new recovery mode (Option-Command-R). Checking again in Disk Utility looks fine.

Setup

The following steps are:

  • Create a default (admin) user as part of the installation, but don’t use the usual name to avoid conflicts later. Try "Migrator".
  • Do NOT create a standard user.
  • Connect the Time Machine Backup drive and enter its password.
  • Launch Migration Assistant and restore from the Time Machine backup.
  • Restore all files, including those of our standard user (write down the temporary password). Promote the admin user to be admin.
  • Wait for an hour...
  • Re-install applications (which have not been backed-up).
  • Login, change password, re-authenticate iCloud.
  • Correct file ownership of the Things database, from the admin account:

    % sudo chown gollum "/Users/gollum/Library/Containers/com.culturedcode.things/Data/Library/Application Support/Cultured Code/Things/ThingsLibrary.db"
    
  • Delete the Migrator user.