The Confusatory

cbowns’s tumblr.

  1. Technical Reading Tuesday

    I’ve used steipete's PSPDFKitImproveRecursiveDescription for years: when debugging an iOS application, it prints out a ton more information about the view hierarchy than the default [UIView recursiveDescription] method. It prints out the owning view controller for a view, child view controllers, and frames which overlap or are zero-sized. I’ve got a fork of the gist which builds successfully for iOS 7.


    I went crawling through steipete's gists earlier last week, and found just a ton of gems. Some of these are tactical strike-force fixes for odd/buggy UIKit behaviour, or debug-only (like the improved recursiveDescription gist), or should just generally be handled carefully.

    Macros, niceties, scripts, etc:

    Hacking inside UIKit:

  2. Mark up your methods with nonnull

    clang supports a neat markup attribute called nonnull. NSHipster has more information about it. You can use this attribute to indicate to the compiler if any (or all) parameters to a method should not be nil/NULL.

    This is especially useful for methods which take block parameters. For a method which takes a block to provide optional additional behaviour, it’s common to pass a nil block when the caller doesn’t need to do additional work, like completion:nil for UIKit animation blocks. When writing your own methods which accept a block as a parameter, mark up the method with nonnull, and the compiler will help provide a compilation-time backstop to callers who mistakenly misuse the API. (Especially clever callers can still defeat the compiler’s ability to detect a passed nil, so you should continue to be defensive and check the block parameter as non-nil before calling it. After all, calling a nil block will crash your application.)

    nonnull takes a comma-delimited list of parameters (starting at 1) which should be non-null. You can also elide the parameter numbers, which is interpreted as “all parameters should not be null”.

    Example usage: all parameters should be non-null:

    - (void)uploadFile:(NSURL *)file
            completion:(void (^)())onComplete
      __attribute__((nonnull ()));
    

    Usage with a BOOL parameter, which can’t be non-null-checked:

    - (void)uploadWithProgress:(BOOL)showProgress
            completion:(void (^)())onComplete
      __attribute__((nonnull (2)));
    

    gparker pointed out that this attribute has been improved in recent clang builds to support in-line markup as well, though this is not supported in Xcode 5.1. When it is in a public Xcode build, it’ll look like:

    - (void)uploadFile:(NSURL *) __attribute__((nonnull)) file
            completion:(void (^)())onComplete;
    
  3. iOS Permissions: Respecting the User

    [Ed: apologies for linking to TechCrunch. We try to avoid it.]

    There’s an excellent article written by Cluster about prompting users for location services, photo album access, and receiving push notifications.

    iOS’s dialog box-based permission granting system for photos, location, etc. has been widely accepted as “Works Well (Enough)”. However, if a user selects “Don’t Allow” in a dialog, and wishes to change it later, they have to exit the application and go through several steps to change it.

    five-step user permission access flow in iOS 7

    From the application’s perspective, this is difficult to guide users through successfully (and even harder to make sure they make it back to your app).

    Cluster implements several alternate approaches, which I believe are better both for the application and for the user:

    • They show a native iOS dialog asking if the user wants to grant access, and only if the user says “yes” do they show the actual iOS dialog for accessing photos (or location, etc).
    • They implement UI that makes it clear what the advantages are to granting access.
    • They educate and inform the user about the dialog that’s about to come, what it’s for, and why it’s appearing.

    I like these approaches a lot. They contextualize and inform the user about the permissions and data access they’re granting. They allow a user to judge the requested access on merit and the value it will yield, rather than being faced with a hostile “the app wants your location right now yes or no?!” dialog at launch (or a barrage of several in a row).

  4. Remapping Keyboard Commands in Sublime Text 2: Embrace the Disassembler

    Sublime Text 2 is a highly extensible GUI text editor for OS X, Windows, and Linux.

    It contains a simple system for users to remap its commands’ keyboard shortcuts. On OS X, I traditionally ack through ~/Library/Application Support/Sublime Text 2/Packages/Default/Main.sublime-menu and find the title of the menu item I’m looking to change. Remapping it is simple: following the directions, you add a line like: { "keys": ["command+option+r"], "command": "filter_through_command" } to your user keymap, and the new shortcut takes effect immediately.

    I wanted to remap a command which had no menu entry, though: the Find box’s “Regular Expression” toggle. Searching through all the usual keymaps came up empty when searching for it, “Whole Word” (another Find box toggle), and others. otx (a disassembler built on top of otool, installable via homebrew's headonly repository), however, found a result in the application’s binary:

      +467  00000001000b9853  488d358b503f00            leaq        0x3f508b(%rip), %rsi          icon_regex
      +474  00000001000b985a  488d0d8f503f00            leaq        0x3f508f(%rip), %rcx          Regular expression
      +481  00000001000b9861  4c8d059b503f00            leaq        0x3f509b(%rip), %r8           toggle_regex
      +488  00000001000b9868  4c89ff                    movq        %r15, %rdi
      +491  00000001000b986b  e80ad9f7ff                callq       icon_button_panel::add_toggle_button(char const*, observable<bool>*, char const*, char const*)
      +496  00000001000b9870  498d96e0010000            leaq        0x1e0(%r14), %rdx
      +503  00000001000b9877  488d3592503f00            leaq        0x3f5092(%rip), %rsi          icon_case
      +510  00000001000b987e  488d0d95503f00            leaq        0x3f5095(%rip), %rcx          Case sensitive
      +517  00000001000b9885  4c8d059d503f00            leaq        0x3f509d(%rip), %r8           toggle_case_sensitive
      +524  00000001000b988c  4c89ff                    movq        %r15, %rdi
      +527  00000001000b988f  e8e6d8f7ff                callq       icon_button_panel::add_toggle_button(char const*, observable<bool>*, char const*, char const*)
      +532  00000001000b9894  498d9600020000            leaq        0x200(%r14), %rdx
      +539  00000001000b989b  488d359d503f00            leaq        0x3f509d(%rip), %rsi          icon_whole_word
      +546  00000001000b98a2  488d0da6503f00            leaq        0x3f50a6(%rip), %rcx          Whole word
      +553  00000001000b98a9  4c8d05aa503f00            leaq        0x3f50aa(%rip), %r8           toggle_whole_word
    

    In the above disassembly, you’ll notice the usual underscore-named commands appear as plain text. Those are exactly what I needed to add to my user keymap!

    { "keys": ["control+command+r"], "command": "toggle_regex"}
    
  5. Xcode plug-ins that make my day a tiny bit brighter

    There’s been an explosion in Xcode plugins in the past few years and I’ve jumped in wholesale. I’m using Alcatraz to manage these: it’s much easier than manually cloning the repositories for these into Xcode’s Application Support folder. Here’s what I’m using. (Last updated May 28, 2014.)

    BBUDebuggerTuckAway “auto-hid[es] the debugger once you start typing in the source code editor”. It’s lovely.

    GIF of auto-hidden debugger when you start typing in the source editor

    In a similar vein, BBUUtilitiesTuckAway auto-hides the utilities sidebar when you start typing in the source code editor. This is especially useful when flipping between a storyboard/XIB project back to source code.

    FuzzyAutocomplete “patches the autocomplete filter to work the same way the Open Quickly works. It performs very well, and the fuzzy matching actually uses Xcode’s own IDEOpenQuicklyPattern.”

    GIF of fuzzy autocomplete in action

    Adjust Font Size increases or decreases font size with ⌘+ or ⌘–.

    SCXcodeMiniMap bring Sublime Text’s minimap to Xcode.

    Xcode with a source minimap

    IntelliPaste “makes copy-pasting between header and method files easier”. When you copy a method implementation from a .m and paste it into a .h, it pastes just the method signature.

    GIF of IntelliPaste

    Jumper lets you move up and down in the source file by ten lines with ⌥-↑ and ⌥-↓.

    OMColorSense makes makes working with UIColor (and NSColor) more visual. “When you put the caret on one of your colors, it automatically shows the actual color as an overlay, and you can even adjust it on-the-fly with the standard Mac OS X color picker. The plugin also adds some items to the Edit menu to insert colors and to disable color highlighting temporarily. These menu items have no keyboard shortcuts by default, but you can set them via the system’s keyboard preferences (Xcode’s own preferences won’t show them).”

    Backlight highlights the current line in the source editor.

    The Xcode source editor with the current line highlighted

    Xprop “excludes @property and @synthesize items from the navigator menu.”

    BBUFullIssueNavigator expands the content for all issues content in the issue navigator.

    KSImageNamed (on GitHub) is what first got me hooked on Xcode plugins. When you write an imageNamed: call for NSImage or UIImage, it shows a popup populated with all the images in your project:

    imageNamed: popup screenshot

    HOStringSense displays the character count of an NSString when the text cursor is inside the string, and can also present a popup interface to edit the string in a multiline-aware editor:

    GIF of string editing in a popover

    Dave Keck’s fixins add lots of small features to Xcode. Most of these have been superseded by newer plugins or don’t work in Xcode 5, but I mention them for completeness.

    XcodeColors enables colors in the Xcode debug terminal. CocoaLumberjack will colorize its output if it’s being printed to a terminal that supports color (such as xterm-color or xterm-256color), and is wired up to work with XcodeColors. (You’re using CocoaLumberjack, right? You should be.)

    I’m trying out Dash with OMQuickHelp to see if I prefer using Dash to Xcode’s built-in documentation viewer.

    I found many of these plugins via A Few Helpful Xcode Plugins and The best Xcode plugins, and many more by browsing Alcatraz.

  6. Speaking of HTML animations… Nick Kwiatek

    Speaking of HTML animations… Nick Kwiatek

  7. Things I’m Reading

    • Several pieces by Aaron Swartz. Start at the top and just take it all in. I’m so disappointed in myself that I hadn’t read his work earlier, and am all the more saddened by his death.
  8. Time is a Dimension

    Time is a dimension.

    Golden Mile Complex Sunset, 2014

    Golden Mile Complex Sunset

    HDB Rainbow Sunset, 2014

    HDB Rainbow Sunset, 2014


    Time in motion. Click for huge version.

    Glassy Sunset, 2013

    Animated gif of a sunset reflected on a building