Few miscellaneous notes from the world of iOS development.

Watch out for that keyboard

If some of the UI tests suddenly start failing for no reason, make sure that Simulator's Connect Hardware Keyboard setting is off. To avoid this issue, the following AppleScript1 might come handy:

-- SwitchKeyboard.applescript
on run argv
  set Simulator to "Simulator"
  tell application Simulator to activate

  set wantChecked to ("0" is not (item 1 of argv))

  tell application "System Events"
    tell process Simulator
      tell menu bar 1
         tell menu bar item "Hardware"
           tell menu 1
             tell menu item "Keyboard"
               tell menu 1
                 set isChecked to ("✓" is (value of attribute "AXMenuItemMarkChar" of menu item "Connect Hardware Keyboard") as string)
                 if wantChecked is not (isChecked is true) then
                   click menu item "Connect Hardware Keyboard"
                 end if
               end tell
             end tell
           end tell
         end tell
      end tell
    end tell
  end tell
end run

You'd then use the above script in your CI pipeline, or run the test-suite from the command line, like so:

osascript SwitchKeyboard.applescript 0 # make sure 'Hardware Keyboard' is off
xcodebuild test ...

As an alternative, you could also simply run defaults write com.apple.iphonesimulator ConnectHardwareKeyboard 0, but then you'd need to restart the simulator (or create a new one).

LLDB

Even disregarding the mentioned keyboard issue, UI testing can at times be finicky2. To see the current view hierarchy, try po XCUIApplication().debugDescription when paused in the debugger; also try wrapping this call with a print() for a nicer output. On a more general note, check out Chisel.

Search & replace regex pairs

These regex-pairs came handy when we added a linter to an existing project.

  • migrate to newer Swift constructors:

    CGRectMake\((.*)\, (.*)\, (.*)\, (.*)\)
    CGRect\(x: $1\, y: $2\, width: $3\, height: $4\)
    
    CGPointMake\((.*), (.*)\)
    CGPoint\(x: $1, y: $2\)
    
  • remove trailing whitespace, but leave whitespace-only lines:

    ([^ \t\r\n])[ \t]+$
    $1
    
  • shorten all CGRectGet*:

    CGRectGet(Width|Height|MaxX|MaxY)\((.*?)\)
    $2\.$1
    

Here's where you'd use one of these regex pairs in Xcode:

Regex replacement in Xcode

Pre-recorded test data

There's a "hidden" setting Test Application Data for mocking test data which really comes in handy when you'd like to launch tests from a known state. Among other uses, having such known state is pretty much essential for any thorough testing of Core Data migrations.

First go to Window > Devices and download the data container from your device:

Download container from device

Then open the Edit Scheme... screen and load the just download .xcappdata:

Edit schema

Note that from Xcode 6 to including Xcode 7.3 this might not be working on the iOS Simulator.

Interviewing

Foolproof question when interviewing for a 'senior' position:

Can you describe at least one downside of Storyboard Segues?

(Granted, many times looming deadlines overrule any other considerations, such as code architecture and subsequent testability. And merely using Segues doesn't make one a 'bad person'. Yet the question is still ingenious as it doesn't demand any iOS knowledge from you, the hiring manager: all you need to check is does the interviewee think of a response.)

iOS Wonka