Itty Bitty Labs

Code and technical stuff from Itty Bitty Apps.

Integrating Reveal without modifying your Xcode project

So you use Reveal and you love it. But you’ve just fired up a new app in Xcode’s debugger and you want to have a quick look at the internals of the app’s view hierarchy, but you haven’t integrated Reveal via the static or dynamic library yet. What to do?

No problem! LLDB to the rescue.

LLDB can execute arbitrary code inside your running application. So you can just load Reveal into any iOS process you are currently debugging.

Just hit ^⌘Y to pause the iOS app in the Xcode debugger and then at the (lldb) prompt type:

LLDB Commands
1
2
3
expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2);
expr [(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
continue

Simple, right?

OK, so maybe not so simple and easy to remember. Wouldn’t it be better if we could just type reveal_load at the LLDB prompt or something like that?

Well, we can! LLDB supports command aliases. Just like with bash, you can create an alias in LLDB for a more complex command. The syntax is a bit different but the concept is the same. Also, just like bash, LLDB has a ‘dot file’ that it loads every time it starts which is the ideal place to put your LLDB command alises. That dot file is ~/.lldbinit.

Open up your favourite text editor, create the file .lldbinit file in your home directory and chuck the following LLDB command aliases into it:

~/.lldbinit
1
2
3
4
command alias reveal_load_sim expr (void*)dlopen("/Applications/Reveal.app/Contents/SharedSupport/iOS-Libraries/libReveal.dylib", 0x2);
command alias reveal_load_dev expr (void*)dlopen([(NSString*)[(NSBundle*)[NSBundle mainBundle] pathForResource:@"libReveal" ofType:@"dylib"] cStringUsingEncoding:0x4], 0x2);
command alias reveal_start expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStart" object:nil];
command alias reveal_stop expr (void)[(NSNotificationCenter*)[NSNotificationCenter defaultCenter] postNotificationName:@"IBARevealRequestStop" object:nil];

The above snippet creates four command aliases: reveal_load_sim, reveal_load_dev, reveal_start and reveal_stop.

  • reveal_load_sim – This alias only works when running your app on the iOS Simulator. It loads the libReveal.dylib from the Reveal application bundle (assuming you put Reveal in your system’s Applications folder). If you have Reveal elsewhere change the alias to reflect this.
  • reveal_load_dev – This alias works when running your app on device or in the iOS Simulator. It however assumes you have added the libReveal.dylib bundled with Reveal to your application’s Copy Resources build phase. (Make sure it is not in your Link Binary with Libraries build phase. Yes, I was fibbing a little about not having to modify your Xcode project. Sorry.
  • reveal_start – This alias posts a notification via NSNotificationCenter to start the Reveal server.
  • reveal_stop – This alias posts a notification via NSNotificationCenter to stop the Reveal server.

Note: *Invoking the reveal_start command is only required if you invoke one of the reveal_load commands after iOS has posted the UIApplicationDidFinishLaunchingNotification notification. i.e. After your application delegate has handled application::didFinishLaunchingWithOptions:.

With these aliases defined you can now issue these quick commands at the LLDB prompt in Xcode. LLDB even auto-completes them for you!

Ok so now you have some quick LLDB command aliases and can trigger them manually, how do you make it more automatic?

Breakpoints!

Xcode (LLDB really) can execute commands in response to breakpoints. Using this knowledge we can add breakpoints to our application that load and start Reveal automatically.

The image above shows how you can add the Reveal LLDB commands to a break point in Xcode.

Some things to note about this breakpoint:

  • The break point is set to continue automatically so that the debugger doesn’t stop your app from executing when it loads Reveal.
  • Both the load and start commands are being executed. If you place your breakpoint in (or before) application:didFinishLaunchingWithOptions: you don’t have to actually issue the reveal_start command. Reveal automatically listens for UIApplicationDidFinishLaunchingNotification and starts automatically when this notification is fired by an app. There is no harm in trying to start Reveal twice. You might just see duplicate log messages.

When the breakpoint commands are successfully executed by LLDB you will see something like the following in the debugger console:

1
2
(void *) $0 = 0x0000000109022350
2013-11-07 15:18:20.687 Test[18049:70b]  INFO: Reveal server started.

Now you’re armed with LLDB and Reveal super powers!


About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

Xcode and the case of the disappearing quick help

Recently I was coding in Xcode 5 (not something I tend to do much as an AppCode user), and I noticed a bug when trying to view the quick help for a symbol. This is usually done by option clicking on a symbol in the Xcode editor pane. The quick help popup window would show up and then rapidly shrink down to nothing. Most mysterious.

You can see this effect in the embedded video below.

This behaviour is not good, so I filed it as a bug with Apple (rdar://15285710). Apple’s bug report team helpfully got back to me today and I was informed that if I removed an Xcode preference the problem would go away.

I made sure Xcode wasn’t running and then issued the following defaults command at the terminal command line:

1
defaults delete com.apple.dt.Xcode WebKitJavaScriptEnabled

On relaunching Xcode the quick help popup was back to behaving as it should.
Great success!


About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

Reveal tips: Navigation

Some of the awesome features of Reveal have been going unoticed, so I have written a quick rundown of how to improve your Reveal workflow so you can navigate your app like a pro.

And here is the tl;dr video:

Navigating the hierarchy

The outline view gives you a detailed one-for-one representation of the application’s view hieararchy. For a lot of apps, their view hierarchy will be massive, and sometimes scrolling and clicking just doesn’t cut it. My most used shortcut in Reveal has to be selecting the current view’s superview for those times I clicked the wrong view in the canvas.
These are the shortcuts that help you pop around the tree with ease:

  • Select current views’s superview [
  • Select current views’s first subview ]
  • Select current views’s next sibling
  • Select current views’s previous sibling ;

Because the outline uses native OS X controls, system defaults for expanding and collapsing nodes are the same as Finder

  • Collapse all nodes from the current selection
  • Expand all nodes from the current selection

Canvas viewing options

Now, one of the most eye-zappingly-awesome parts of Reveal is the 3d Canvas, which has quite a few features that people are yet to discover. There is a collection of mouse/trackpad combos to pan, rotate and increase the z-depth of the 3d representation.

  • Pan Up/Down two finger up/down or mouse-wheel
  • Pan Left/Right two finger left/right or mouse-wheel
  • Rotate two finger left/right or mouse-wheel
  • Z-Depth two finger pinch or mouse-wheel

Easy management of Zoom levels:

  • Zoom in + or two finger pinch
  • Zoom out or two finger pinch
  • Zoom to actual size 0
  • Zoom to fit 9
  • Zoom to current selection 8

Gaining some focus

Reveal lists every* UIView in the view hierarchy from the UIScreen down. Because that easily becomes an excessive amount of views to scroll through, Reveal allows you to drill-down and isolate your focus on a particular subset by simply double clicking a view:

I personally use this focussing a lot, especially when iterating with designers or any time I have to manipulate a UITableViewCell.
Once ‘focussed’ on a subset of the view hierarchy, you can navigate your way back up the tree using the path-bar at the top of the canvas. This is really helpful for those times you accidently double-clicked a view that was in front of the view you wanted to focus on.
You can also go back and forth in your focus history with the left/back buttons or the key-board shortcuts:

  • Back in Focus History ^
  • Forward in Focus History ^

* Reveal cannot see into a UIRemoteViewControllers’ views such as MFMailComposeViewController

File /Users/seanw/Projects/iba/iba/ittybittyapps.github.io/source/includes/about_peter.markdown could not be found

iOS 7 & UITextView’s UITextInputTraits bugs

Today while working on Reveal I became aware of a bug in iOS 7’s UITextView’s handling of the UITextInputTraits protocol.

The UITextInputTraits protocol has methods for setting what sort of keyboard should be shown when a user taps on a UITextView and other such things.

iOS 7 also introduced a new selectable property on UITextView for controlling whether text selection is enabled. This is much better than the methods required in previous releases of iOS, where you had to subclass UITextView and return no for canBecomeFirstResponder or alternatively set an inputDelegate and handle the appropriate delegate callbacks to stop selection for occurring.

Unfortunately, setting both editable and selectable to NO in iOS 7 breaks all of the UITextInputTraits methods. If you attempt to call any of them your app will crash with an instance does not respond to selector exception. Which is weird because the UITextView instance will return YES if you call respondsToSelector: for any of the methods declared in the UITextInputTraits protocol.

This appears to me to be a bug in iOS 7. I’ve reported it to Apple as radar://15063164.

I’ve also noticed that for UITextView’s created via code (rather than in Storyboards) this bug doesn’t express. I’m not sure why yet. There may be additional properties at work or the fact that the in a Storyboard a UITextView is initialised via initWithCoder: rather than initWithFrame: and may be in a different state due to this.

Some code that shows the bug:

IBAViewController.m
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
59
60
61
62
63
64
65

@interface IBAViewController ()

@property (strong, nonatomic) IBOutlet UITextView *editableAndSelectable;
@property (strong, nonatomic) IBOutlet UITextView *selectable;
@property (strong, nonatomic) IBOutlet UITextView *notEditableOrSelectable;

@end

@implementation IBAViewController

- (void)viewDidLoad
{
  [super viewDidLoad];

  /* 
  Remove the define below and we won't crash on the last NSAssert below.  Leave it in
  and we crash (assuming we've created and connected three UITextView's to the IBOutlets above
  in a storyboard for this view controller).
 */
  
#define USING_STORYBOARD
  
#ifndef USING_STORYBOARD
  self.editableAndSelectable = [[UITextView alloc] initWithFrame:self.view.bounds];
  self.selectable = [[UITextView alloc] initWithFrame:self.view.bounds];
  self.notEditableOrSelectable = [[UITextView alloc] initWithFrame:self.view.bounds];

  [self.view addSubview:self.editableAndSelectable];
  [self.view addSubview:self.selectable];
  [self.view addSubview:self.notEditableOrSelectable];
#endif

  self.editableAndSelectable.text = @"Text1";
  self.editableAndSelectable.editable = YES;
  self.editableAndSelectable.selectable = YES;
  
  self.selectable.text = @"Text2";
  self.selectable.editable = NO;
  self.selectable.selectable = YES;

  self.notEditableOrSelectable.text = @"Text3";
  self.notEditableOrSelectable.editable = NO;
  self.notEditableOrSelectable.selectable = NO;
  
  NSAssert(self.editableAndSelectable.editable == YES, @"Huh?");
  NSAssert(self.editableAndSelectable.selectable == YES, @"Huh?");
  
  NSAssert([self.editableAndSelectable respondsToSelector:@selector(isSecureTextEntry)], @"Huh?");
  NSAssert([self.editableAndSelectable isSecureTextEntry] == NO, @"Huh?");

  NSAssert(self.selectable.editable == NO, @"Huh?");
  NSAssert(self.selectable.selectable == YES, @"Huh?");
  
  NSAssert([self.editableAndSelectable respondsToSelector:@selector(isSecureTextEntry)], @"Huh?");
  NSAssert([self.editableAndSelectable isSecureTextEntry] == NO, @"Huh?");

  NSAssert(self.notEditableOrSelectable.editable == NO, @"Huh?");
  NSAssert(self.notEditableOrSelectable.selectable == NO, @"Huh?");
  
  NSAssert([self.notEditableOrSelectable respondsToSelector:@selector(isSecureTextEntry)], @"Huh?");
  NSAssert([self.notEditableOrSelectable isSecureTextEntry] == NO, @"Huh?"); // crashes here (on iOS 7)
}

@end

About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

Refactoring in Xcode 5

I have a confession to make. I’m an AppCode user. I hardly use Xcode at all.

Ok, so if you know me or have seen my Cocoaheads talk/ramble regarding AppCode you probably already know this.

If you’ve never used AppCode before I suggest you take a look at it, and in particular play with its support for refactoring. Some people can’t get past AppCode’s slightly ugly Java based UI, but if you do get to know AppCode’s keyboard shortcuts and power features I think you will agree it is hard to beat as a Cocoa development tool. It makes me a much more productive developer. I feel like some of my fingers have been removed when using Xcode.

But I digress, this post isn’t about AppCode, it is about Xcode. How to get it to act more like AppCode. Err…. I mean, expose Xcode’s (somewhat limited) refactoring abilities in a better way than is the default, and also to learn about the small in number but still useful code navigation shortcuts Xcode has.

Refactoring Keyboard Shortcuts

Xcode has some limited support for global code refactoring. Tucked away in the Edit menu is the Refactor sub-menu. None of the items in this menu have keyboard shortcuts by default which makes them about as useful as a poke in the eye.

We are going to correct this considerable oversight.

You can edit any of Xcode’s keybindings in its Preferences on the Key Bindings tab. Here you can search the list for all the Refactoring items by typing refactor in the search field. Then double click in the Key column to enable the shortcut editor and then press the key combo you want to use. Xcode will tell you if you’ve created a conflict with an existing key binding. Finding a key combo you like that doesn’t have an existing binding, and thus conflict, can involve a bit of trial and error.

What do these refactoring things do?

Apple has some documentation on the refactoring workflows here. It is always a good idea to consult the official documentation. Below I provide a quick synopsis of the main refactoring actions.

  • Rename – Rename should be obvious. It lets you rename methods, classes, etc and have those changes applied across your entire codebase. Think of it as a smart, semantic, find and replace.
  • Extract – Extract gives you the ability to extract a piece of selected code into a new method or function. It will try and smartly determine what parameters and return values to give the new method based on surrounding code.
  • Move Up – These actions allow you to move a method, property or instance variable up to its super class.
  • Move Down – You would think that Move Down would do the inverse of Move Up, and it does, kinda. Unfortunately it only works with instance variables. Which makes it not as useful as Move Up which can also move methods.
  • Encapsulate – Encapsulate is useful for when you want to convert all uses of an instance variable to into accessor methods, thereby encapsulating that instance variable behind those methods.

Once you’ve added key bindings for these refactoring actions I encourage you to experiment with what they do. Try them out on parts of your code. You may discover that you quickly come to rely on some of them in your day-to-day coding activities.

A note about Snapshots

When you first use a refactoring action in Xcode it prompts you to enable Snapshots. I don’t know if anyone has actually clicked the Enable button in the entire history of Xcode. But if you’re worried about Xcode accidentally obliterating your code, it is there if you want to use it. But you use source control right? So that shouldn’t be a problem, right?

Important: One thing to be aware of however if you do not enable snapshots is that Xcode’s support for undoing changes made by a refactoring is a bit limited without a snapshot. Even when you do save a snapshot restoring the snapshot doesn’t always restore your project perfectly. It might leave you with changes you will need to un-stage in your git repo. This is probably most important to remember when performing a rename refactoring on a class or method used widely in your project.

If you do want to enable/disable snapshots for mass edits like refactoring actions you can do so in File -> Project Settings (or File -> Workspace Settings if you’re using a workspace).

Note also that you can create a snapshot at anytime with ^⌘S. Restoring a snapshot doesn’t have a default key binding. It is in the Xcode File menu. You can manage your project’s snapshots in the Xcode Organizer on the Projects tab.

Other Essential Xcode Keyboard Shortcuts

Edit All in Scope

Although Xcode provides a Rename refactoring action. This action, like all the Xcode refactoring actions, has quite a heavy UI. A quicker more constrained way of renaming things like variables is to use Edit All in Scope ^⌘E which is in the Editor menu. This gives you a quick in-line rename action for renaming variables, parameters, methods and the like. It only changes items in the current scope (and file) so it won’t rename methods in the header or usages in other files like the Rename refactoring action does but it is good for quick local scope renames.

Jump to Definition

Another essential keyboard (and mouse) shortcut to know is Jump to Definition ^⌘J When your cursor is on a symbol (method, variable, whatever) you can press this key combo to quickly jump to the definition (or if you are on the definition to the declaration) of that symbol. Very handy.

You can do this with the mouse too, just hold when you click on a symbol in your code.

Open Quickly

Probably the most essential keyboard shortcut in your Xcode arsenal is Open Quickly ⇧⌘O. You should be using this keyboard combo all day to quickly jump around your code. You can search for symbols and filenames in this dialog. Also note that you can use abbreviations and partial matching in the open quick search field. So if you have a View Controller subclass named AwesomeViewController in your project you can search for AweVC in Open Quickly and it will be found.

Hopefully you’ve found these Xcode tips and hints from an AppCode user to be useful.


About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

Lifting the lid on the iOS 7 UIPicker

Updated April 28th, 2014: The issues discussed in this article relating to the tap areas and consistency of the iOS 7.0 UIDatePicker have been fixed in iOS 7.1. In particular, you can now scroll the AM/PM column by dragging above or below the text, and you can tap a value in the minutes and AP/PM column to select the value. The expanded tap areas mean the picker is easier to use, particularly when embedded in a UITableView.

It’s great to see Apple addressing these issues in point updates, though it seems to confirm that iOS 7.0 was rushed and I’m still not a fan of the 3D effect in a predominantly flat UI. It’ll be interesting to see what they have in store for iOS 8.0.


One of the significant visual changes in iOS 7 is the ‘flattening’ of the UIPicker, and by association the UIDatePicker. On the surface, the new picker looks much cleaner. I’ve never been a fan of the heavy-handed visual treatment given to the iOS 6 picker, and the pseudo 3D rotational effect using gradient overlays probably grated on most anal engineering and designer types. ‘They’re faking it!’, I thought. So when the new iOS 7 picker arrived on the scene there was a piece of me that thought, ‘cool, they’ve cleaned it up and done the 3D effect properly’. That was until I got to use the thing.

I found the new picker quite visually pleasing initially but having used it, I’m not so sure. For example, the UIDatePicker has simplified the colour palette to black and grey, which makes it harder to distinguish the day from the month. The colour highlight on ‘Today’ has been lost too. They’ve also squeezed in an extra two rows above and below the selection, which from an information density perspective is great, but it has reduced the hit areas of each row. Worse than that, the hit areas on the UIDatePicker are inconsistent (Fixed in iOS 7.1). Marc Edwards summarised some of these issues a few weeks ago in this tweet.

As you can see from Marc’s diagram, you can no longer drag above and below the AM/PM column to move it. This is a huge pain because now you have to place your finger over the content in order to make your selection. In iOS 6 I’d often push or pull underneath the selected AM/PM value to change it. You’re also not able to tap the AM/PM or minute items to select them, which is completely inconsistent because you can tap the day and hour items! WAT (Fixed in iOS 7.1)

To add insult to injury, the hit area in the iOS 7 UIDatePicker does not extend to the boundaries of the control. The actual hit area is highlighted in blue below. So now you can’t fat-finger the edges of the picker either. (Fixed in iOS 7.1)

The inset tap area causes real problems when the picker is placed inline within a UITableView. It’s the same old ‘scroll views within scroll views’ conundrum developers have been struggling with since the dawn of graphical user interfaces, but made worse because you can easily miss the tap area within the control’s bounds and end up inadvertently scrolling the whole UITableView. (Fixed in iOS 7.1)

Don’t get me wrong, I think inline pickers are the way to go. It puts them in context with what you’re doing and avoids the issues of placement consistency across the iPhone and iPad. I just wish the tap targets were easier to hit and extended out to the bounds of the control.

Another issue I have with the picker is that Apple have stripped back so much of the ornamentation and deferred so much to the content that pickers with only a small amount of content can look downright weird. Without fully populated rows the transformed text looks out of place and at a glance it’s hard to tell why. It’s not until you move it that it makes sense.

Under the bonnet

From a usability point of view, the new UIPicker has taken one step forward and a few steps back. But the fun really starts when you take a look under the covers.

Here’s the iOS 6 UIDateTime picker view hierarchy displayed in Reveal.

…and here’s the iOS 7 UIDateTime picker.

As you can see, they’ve gone to town with the new implementation. It’s pretty obvious why performance would suck on lower-end devices. Impressive as the 3D transforms on the cells are, it’s hard not to feel like this is overkill for the magnified tumbler effect. The UIDatePicker contains no less than 12 UITableViews with each cell having its own unique 3D transform. The hierarchy is further bloated by the fact that UITableViewCell in iOS 7 introduces a UITableViewCellScrollView that contains the UITableViewCellContentView, neither of which appear to be utilised in the UIDatePicker.

Whether the UIPicker was implemented this way on purpose or not, I don’t know, but it’s certainly not optimised. Maybe Apple really did want the latest version of iOS to push the performance boundaries, but unlike the navigation bar blur effects which were ramped down on poorer performing devices, the implementation of the UIPicker doesn’t support this kind of fallback.

So that’s the new iOS 7 UIPicker. I was left wondering whether the 3D rotation effect was really worth it, both in terms of performance and usability. I’m not even sure the effect has a place in a predominantly flat UI. I can’t see it changing any time soon but I wouldn’t be surprised to see a few fixes and optimisations from Apple in subsequent releases to address some of the issues mentioned above. Watch this space.

If you want to have a peek under the covers yourself, get on over to http://revealapp.com and give Reveal a spin.


About Sean

Sean Woodhouse is the director of Itty Bitty Apps, creators of the iOS runtime inspection tool Reveal. You can follow him on twitter @seanwoodhouse


Upgrade all the XIBs

Xcode 5 was released today along with iOS 7. If you are an iOS or MacOS X developer who uses XIBs and Storyboards in their projects, one of the most significant features to be added to Xcode 5 is the new file format for these files.

If you are a Cocoa developer who has sworn off using XIBs and Storyboards because of the old file format and the trouble that it brings with merging and understanding, it is time to reconsider your position.

You may be asking, why is this such a huge event? Well, in the past this is what XIBs looked like:

Xcode 3.x & 4.x style XIB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
<?xml version="1.0" encoding="UTF-8"?>
<archive type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="8.00">
  <data>
      <int key="IBDocument.SystemTarget">1080</int>
      <string key="IBDocument.SystemVersion">12E55</string>
      <string key="IBDocument.InterfaceBuilderVersion">3084</string>
      <string key="IBDocument.AppKitVersion">1187.39</string>
      <string key="IBDocument.HIToolboxVersion">626.00</string>
      <object class="NSMutableDictionary" key="IBDocument.PluginVersions">
          <string key="NS.key.0">com.apple.InterfaceBuilder.CocoaPlugin</string>
          <string key="NS.object.0">3084</string>
      </object>
      <array key="IBDocument.IntegratedClassDependencies">
          <string>IBNSLayoutConstraint</string>
          <!-- ... -->
          <string>NSTextFieldCell</string>
      </array>
      <array key="IBDocument.PluginDependencies">
          <string>com.apple.InterfaceBuilder.CocoaPlugin</string>
      </array>
      <object class="NSMutableDictionary" key="IBDocument.Metadata">
          <string key="NS.key.0">PluginDependencyRecalculationVersion</string>
          <integer value="1" key="NS.object.0"/>
      </object>
      <array class="NSMutableArray" key="IBDocument.RootObjects" id="1000">
          <object class="NSCustomObject" id="1003">
              <string key="NSClassName">FirstResponder</string>
          </object>
          <object class="NSCustomView" id="1005">
              <reference key="NSNextResponder"/>
              <int key="NSvFlags">268</int>
              <array class="NSMutableArray" key="NSSubviews">
                  <object class="NSTextField" id="614930396">
                      <reference key="NSNextResponder" ref="1005"/>
                      <int key="NSvFlags">268</int>
                      <string key="NSFrame">\{\{42, 2\}, \{287, 14\}\}</string>
                      <reference key="NSSuperview" ref="1005"/>
                      <reference key="NSWindow"/>
<!-- etc.... -->

The files were huge, nasty messes of XML that Xcode would change and re-order on a whim. While it might have been possible to build a mental model of what user interface the XIB represented it was very hard so no one bothered.

With Xcode 5 XIBs are still XML but they are now XML that a human might write by hand. Eg:

Xcode 5.x style XIB
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30

<?xml version="1.0" encoding="UTF-8" standalone="no"?>
<document type="com.apple.InterfaceBuilder3.Cocoa.XIB" version="3.0" toolsVersion="4510" systemVersion="12F37" targetRuntime="MacOSX.Cocoa" propertyAccessControl="none" useAutolayout="YES">
    <dependencies>
        <deployment defaultVersion="1080" identifier="macosx"/>
        <plugIn identifier="com.apple.InterfaceBuilder.CocoaPlugin" version="4510"/>
    </dependencies>
    <objects>
        <customObject id="-2" userLabel="File's Owner" customClass="IBAAppSummaryTitleViewController">
            <connections>
                <outlet property="appNameTextField" destination="2" id="222"/>
                <!-- ... -->
                <outlet property="view" destination="1" id="66"/>
            </connections>
        </customObject>
        <customObject id="-1" userLabel="First Responder" customClass="FirstResponder"/>
        <customObject id="-3" userLabel="Application"/>
        <customView id="1" customClass="IBABarView">
            <rect key="frame" x="0.0" y="0.0" width="346" height="31"/>
            <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
            <subviews>
                <imageView translatesAutoresizingMaskIntoConstraints="NO" id="121">
                    <rect key="frame" x="8" y="1" width="29" height="29"/>
                    <autoresizingMask key="autoresizingMask" flexibleMaxX="YES" flexibleMinY="YES"/>
                    <constraints>
                        <constraint firstAttribute="width" constant="29" id="141"/>
                    </constraints>
                    <imageCell key="cell" refusesFirstResponder="YES" alignment="left" imageScaling="proportionallyDown" image="ipad-icon" id="122"/>
                </imageView>
<!-- etc.... -->

The benefits of this new XIB XML format are many fold:

  • XIBs are much smaller (fewer lines of code).
  • A developer can easily read the XML and understand what it specifies in the user interface.
  • Merging XIBs is now much less likely to lead to broken XIBs. Before we would rarely even bother to try and merge a XIB or Storyboard.
  • It might be possible for 3rd party tools to be built around the new XIB format. We’ll probably need an actual DTD to be published by Apple for this to be truly reliable though.
  • The new (much better) Auto Layout workflows in Xcode 5 are enabled by the new XIB format.

So if you’ve not done so already I highly recommend updating your project’s XIBs to the new Xcode 5 format. Xcode 5 should prompt you to do so the next time you open a XIB but if it does not you can just change the Interface Builder Document properties in the Xcode inspector for a XIB file and then save the XIB file again (as shown to the right).

Bear in mind that once you upgrade you wont want to go back to Xcode 4 style XIBs (even though it is technically possible). So before you do so ensure that this isn’t going to be a problem for your team or build servers.


Go forth and convert!


About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

git pre-push

Breaking the build never feels good. Thanks to git’s new pre-push hook we can force ourselves to run our tests before we push to master, and prevent any odd punishments our current team has setup.
As of git version 1.8.2 which was released in April 2013, you now have the ability to execute a script on a push, and prevent the push from occuring if your script exits with a failure.

If you’re running OS X 10.9 Mavericks, and you have Xcode 5’s command line tools installed, you will already have a version of git that is pre-push hook ready.

Otherwise if your version is less than 1.8.2, you will need to download, and ensure /usr/local/git/bin is in your path, by adding export PATH=/usr/local/git/bin:$PATH to your ~/.bash_profile
You can test if you have installed correctly with which git and git --version



Enabling the pre-push hook

For each git repository you can find the hooks in the .git/hooks directory. All it takes for a git hook to run, is for there to be an executable file with the appropriate name within this directory. The list of available hooks are:

  • applypatch-msg
  • pre-applypatch
  • post-applypatch
  • pre-commit
  • prepare-commit-msg
  • commit-msg
  • post-commit
  • pre-rebase
  • post-checkout
  • post-merge
  • pre-push
  • pre-receive
  • update
  • post-receive
  • post-update
  • pre-auto-gc
  • post-rewrite

To enable the pre-push hook, just create $YOUR_REPO/.git/hooks/pre-push



Editing your pre-push hook

If the pre-push script exits with a failure (a return status of non-zero) then the push will do nothing. A very basic script to remind yourself that you should run your tests before pushing would look like this:

basic.pre-push.shlink
1
2
3
4
5
6
7
8
9
#!/bin/bash

read -p "You're about to push, are you sure you won't break the build? " -n 1 -r < /dev/tty
echo
if [[ $REPLY =~ ^[Yy]$ ]]
then
    exit 0 # push will execute
fi
exit 1 # push will not execute

This is a pretty silly use-case for pre-push, below are some more practical uses.



Using pre-push as a safety net

Sometimes I want the ability to write a comment on a piece of code/spike that I am doing, and make sure it never goes beyond my machine. Below is a pre-push example that will search the current source for the string ‘DONT PUSH ME’ and if found, will prevent the push and display in which commit the ‘DONT PUSH ME’ flag was introduced.

flag.pre-push.shlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
#!/bin/bash

# If the following text is found anywhere in the source for HEAD, we will prevent pushing
dont_push_flag="DONT PUSH ME"

flag_found=`git grep --color "$dont_push_flag" HEAD`
if [ -n "$flag_found" ]
then
    # Display which commit the first occurence of the flag was found and exit failure
    commit=`git log --pretty=format:'%Cred%h%Creset' -S "$dont_push_flag" | tail -n1`
    echo "Found $flag_found, first occurence was in $commit, not pushing"
    exit 1
fi
exit 0


Using pre-push to only push on successful execution of tests

Below is an example pre-push script that let’s us specify a branch to ‘protect’ so that our tests will only run if there are commits to push and we are on ‘master’. Also because pre-push will execute regardless of if there are commits to push or not, the script ensures we don’t fire off a lengthy test command, only to find out we actually didn’t need to.

tests.pre-push.shlink
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
#!/bin/bash 

CMD="ls -l" # Command that runs your tests
protected_branch='master'

# Check if we actually have commits to push
commits=`git log @{u}..`
if [ -z "$commits" ]; then
    exit 0
fi

current_branch=$(git symbolic-ref HEAD | sed -e 's,.*/\(.*\),\1,')

if [[ $current_branch = $protected_branch ]]; then
    $CMD
    RESULT=$?
    if [ $RESULT -ne 0 ]; then 
        echo "failed $CMD"
        exit 1
    fi
fi
exit 0


Bypassing the pre-push hook

git push --no-verify

If you want to skip your pre-push hook from executing, you can run this and feel dirty about it ;)



Git’s included example

If you have created a repo with a version of git later than 1.8.2, then git has already set you up with a sample pre-push script .git/hooks/pre-push.sample. This script prevents pushing if any of the ‘to be pushed’ commits begin with ‘WIP’, and also details the parameters that are passed into the script.



That’s a wrap

You can find all of the scripts here https://github.com/raven/git-prepush-recipes. Please submit pull requests if you spot any issues, or if you have any pre-push scripts of your own.
If you have any questions or comments, ping me on twitter


About Pete

Peter Goldsmith is an iOS Developer for Itty Bitty Apps and has worked on their amazing iOS introspection tool Reveal. He thinks you should follow him on twitter @peterngoldsmith

Queues to the Rescue

Often when developing applications you want to run some code but only if your application is in a particular state and if the app is not yet in yet in that state, do it later.

One approach would be something like the this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
@interface MyClass : NSObject
- (void)doSomething;
@end

@implementation MyClass

- (void)doSomething
{
  if ([self isActive])
  {
      // do something
  }
  else
  {
      self.doSomethingWhenActive = YES;
  }    
}

- (void)didBecomeActive
{
  self.active = YES;
  if (self.doSomethingWhenActive)
  {
      self.doSomethingWhenActive = NO;
      [self doSomething];     
  }
}

- (void)didBecomeInActive
{
  self.active = NO;
}

@end

Unfortunately there are some problems with this simple (yet naive) solution.

The most problematic aspect of the simple solution is that we’ve introduced state into our class with the doSomethingWhenActive property. We have to remember when this flag should be turned on or off. We’re also potentially managing the state we’re basing our decisions on (the active/inactive state above).

Every time you introduce state, and behaviour that is dependent on that state, into a class you increase the potential for bugs to creep into the code. Eg, which code paths set and clear that state. Is it possible for the boolean state variable to get stuck on or off because we didn’t reset it in a particular code path, etc.

Another problem with this approach is that if we need to add some more behaviour that is performed when our class is “active” or returns to being active (or some other situation) we may have to add yet another boolean property and yet more conditional logic complicating our class’s behaviour and compounding the likelihood of bugs creeping in.

A more robust solution to this sort of situation is to use a work queue.

Here is an example:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
22
23
24
25
26
27
28
29
30
31
32
33
34
35
36
37
38
39
40
41
42
43
44
45
46
47
48
49
50
51
52
53
54
55
56
57
58
@interface MyClass : NSObject
- (void)doSomething;
@end

@implementation MyClass

- (id)init
{
  self = [super init];
  if (self)
  {
      _activeAppTaskQueue = [[NSOperationQueue alloc] init];
      _activeAppTaskQueue.maxConcurrentOperationCount = 1;

      // The active app task queue begins in a suspended state.
      _activeAppTaskQueue.suspended = YES;
  }        
}

- (void)dealloc
{
    _activeAppTaskQueue.suspended = YES;
    [_activeAppTaskQueue cancelAllOperations];
}

- (void)didBecomeActive
{
  _activeAppTaskQueue.suspended = NO;
}

- (void)didBecomeInActive
{
  _activeAppTaskQueue.suspended = YES;
}

- (void)doSomething
{
  [self performBlockWhenActive:^(MyClass *object) {
      // do something with object
  }];
}

- (void)performBlockWhenActive:(void (^)(MyClass *))block
{
  if (block)
  {
      __weak MyClass *myObject = self;
      [_activeAppTaskQueue addOperationWithBlock:^{
          // Active app tasks might need to run on the main queue.
          // This depends on if your class manipulates UI.
          dispatch_async(dispatch_get_main_queue(), ^{
              block(myObject);
          });
      }];
  }
}

@end

In the code above the performBlockWhenActive: method is private and invocations of doSomething use it to enqueue work for execution later. You could make this more general by exposing the performBlockWhenActive: method publicly. Then clients of that class can choose whether they want doSomething to happen immediately or only when the app is active. Eg:

1
2
3
4
5
6
7
8
9
10
@implementation MyOtherClass

- (void)confribulateTheConfabulator
{
  [_stuff performBlockWhenActive:^(MyClass *object) {
      [object doSomething];
  }];
}

@end

Note: The code above uses an NSOperationQueue instead of a GCD dispatch queue so that tasks that have not been executed can be canceled when the MyClass instance is released. If you want all submitted tasks to execute no matter what, you could use a GCD dispatch queue. Then rather than cancelling all the operations before release you would ensure that the queue was resumed (and thus pending task blocks completed). Be careful with suspending/resuming GCD queues however. They will assert/crash your app if calls to dispatch_resume/dispatch_suspend are unbalanced or if you attempt to release a queue while it is suspended.

Also be careful about introducing retain cycles by making references to self (either implicit or explicit) in the task blocks. This is why I pass the MyClass instance that actions should be performed on into the block as a parameter to help avoid this sort of reference cycle.

So although this solution isn’t without its own potential pitfalls and problems I feel it is a better solution than the first simple attempt.

The queue based solution has the benefits of being more general, requiring less state, and executing the tasks in the order they are submitted with performBlockWhenActive:.

I recently employed this pattern in my own code when I needed an application to display a window to the user but only once the app had become the active application.

The call to performBlockWhenActive: was made in a part of the app’s lifecycle that did not guarantee that the application had completed launching yet. The same code however could also be invoked at times when the app was launched and active. By pushing the work into a queue that was only executing when the app was in the active state I was able to solve this issue with the minimum amount of fuss and also provide a facility to the application that could be used in other similar situations.


About Oliver

Oliver Jones is the Technical Director at Itty Bitty Apps. He spends his days building the iOS Introspection tool Reveal and playing Pinball. You can follow him on twitter @orj.

It’s alive!

When I created the very first Itty Bitty Apps web site back in 2009 I had visions of posting regular articles about iOS development and the trials and tribulations of running an iOS consulting company. As it happened, actually running and growing the company meant that the blog section of the Wordpress-backed web site was very seldom updated. I don’t know about you, but I reckon there’s nothing worse than going to a company’s site to see their last post was from two years ago, especially in the mobile arena where things move so fast that posts only a few months old are usually out of date.

Well, here we are in 2013 and Itty Bitty Apps has grown a bunch. Not only do we have some amazing talent on board, but we’re all champing at the bit to share what we know. To that end, we’ve re-booted the company web site as a static S3-hosted site and now, for your reading pleasure, we’re re-booting the blog as an Octopress site hosted on Github Pages.

We’re all really excited about sharing our tips, tricks and learnings, and I expect this blog will become an indispensable resource over time. Expect topics ranging from low level programming tips to insights in to the development and go-to-market of our new iOS developer tool Reveal.

So sit back, turn up the tunes and enjoy.


About Sean

Sean Woodhouse is the director of Itty Bitty Apps, creators of the iOS runtime inspection tool Reveal. You can follow him on twitter @seanwoodhouse