Jim Kubicek

Octo-Impressive

Symbols Not Found When Building a Test Target

I’ve wasted close to an entire day on this bug. I was going back to an old project and updating the tests, which had gotten woefully out of date. Unfortunately, I got the following error during the linking phase.

Undefined symbols for architecture x86_64:
  "_OBJC_CLASS_$_DataController", referenced from:
      objc-class-ref in TestRequestGenerator.o
ld: symbol(s) not found for architecture x86_64
clang: error: linker command failed with exit code 1 (use -v to see invocation)

Almost nothing I was doing was fixing this. I tried deleting and recreating the test target, examining the output binary with nm (DataController was present), creating new test Xcode projects and diffing the linker commands with Kaleidoscope… nothing.

Turns out, the one thing I didn’t look at, the compilation step, was the culprit. In the interest of keeping my debug and release builds as consistant as possible, I had set Symbols Hidden by Default to Yes for both my Release build and Debug builds. Hiding the symbols meant that the test target couldn’t see my DataController.

You Need to Create a UI Test Target

For the last few years, I’ve always created a dummy UITester target in any app I’m working on. This target is something akin unit tests for interface elements. After talking to Matt earlier today we realized that perhaps not everyone knows this trick, and I think it’s something every iOS dev should be doing.

Here’s what this target does: Each new interface element (buttons, sliders, image views, etc.) will have its own testing view controller. This view controller can do whatever needs to be done. It can animate elements, handle touches, run events on timers, fire notifications, or anything else. Iterative development is greatly simplified when you don’t need to run your full app to test whether an element is working as it should. Additionally, any other engineers on your team will be able to use your testing view controller to see how a new element should be used.

Example

I’ve created a dummy app that has two custom interface elements, an OrangeButton and GreenSlider.

The first step is creating a UITester target. Create a new Master-Detail Application in Xcode. For those of you new to Xcode 5 (i.e. everyone) the command to create a new target is accessible by selecting your Project in the Project Navigator and selecting “Add Target…” from the “Editor” menu. Feel free to erase any testing targets one is created, you won’t be using it.

You should open the newly created Main.storyboard and delete the DetailViewController, we won’t be using it. In the project, delete the DetailViewController.[h|m] files as well.

Each interface element should have an associated view controller. This view controller is responsible for displaying the element and handling any user interactions you’d like to test. Go head and create two new view controllers, OrangeButtonViewController and GreenSliderViewController. These should be imported in MasterViewController.m.

Here’s how I like to setup my MasterViewController.

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
66
67
68
69
typedef NS_ENUM(NSUInteger, ElementTestName) {
    ElementTestNameOrangeButton,
    ElementTestNameGreenSlider,

    ElementTestNameCount, // Always last
};

#pragma mark - Private Methods

- (NSString *)nameForElementTestName:(ElementTestName)test {
    switch (test) {
        case ElementTestNameGreenSlider:
            return @"Green Slider";
            break;
        case ElementTestNameOrangeButton:
            return @"Orange Button";
            break;
        case ElementTestNameCount:
            NSAssert(NO, @"Should never get here");
            return nil;
            break;
    }
}

- (UIViewController *)viewControllerForTestName:(ElementTestName)test {
    switch (test) {
        case ElementTestNameGreenSlider:
            return [GreenSliderViewController new];
            break;
        case ElementTestNameOrangeButton:
            return [OrangeButtonViewController new];
            break;
        case ElementTestNameCount:
            NSAssert(NO, @"Should never get here");
            return nil;
            break;
    }
}

#pragma mark - Table View

- (NSInteger)numberOfSectionsInTableView:(UITableView *)tableView
{
    return 1;
}

- (NSInteger)tableView:(UITableView *)tableView
    numberOfRowsInSection:(NSInteger)section
{
    return ElementTestNameCount;
}

- (UITableViewCell *)tableView:(UITableView *)tableView
         cellForRowAtIndexPath:(NSIndexPath *)indexPath
{
    UITableViewCell *cell = [tableView
        dequeueReusableCellWithIdentifier:@"Cell"
                             forIndexPath:indexPath];

    cell.textLabel.text = [self nameForElementTestName:indexPath.row];
    return cell;
}

- (void)tableView:(UITableView *)tableView
    didSelectRowAtIndexPath:(NSIndexPath *)indexPath
{
    UIViewController *vc = [self viewControllerForTestName:indexPath.row];
    [self.navigationController pushViewController:vc animated:YES];
}

Adding a new testing view controller is as simple as:

  1. Add another value to the ElementTestName enum.
  2. Use nameForElementTestName: to return the string that will be visible in the MasterViewController table view.
  3. Use viewControllerForTestName: to return the View Controller that will be pushed onto the nav stack.

And that’s about it. Use the GreenSliderViewController and OrangeButtonViewController classes to setup your interface elements appropriately for testing, and you’re good to go.

State Restoration

If you end up making heavy use of this UITester target, you are going to want to enable state restoration. Iterative development is much easier if the element you’re working on is always open when you restart the app.

First step, you’ll need to give Restoration IDs to the nav controller and tableview controllers in your Main.storyboard. Use caution and make sure you are giving the restoration ID to the view controller, not one of it’s views.

Next, enable state restoration in the UITester target. In the app delegate, add the following lines.

1
2
3
4
5
6
7
8
9
10
11
- (BOOL)application:(UIApplication *)application
        shouldSaveApplicationState:(NSCoder *)coder
{
    return YES;
}

- (BOOL)application:(UIApplication *)application
        shouldRestoreApplicationState:(NSCoder *)coder
{
    return YES;
}

Each view controller in your app should have its restoration ID set. I found that, for an simple app like this, having a superclass handle the restoration is the way to go. All my testing view controllers are subclasses of a RestorableViewController class. Here are the contents of its .m file.

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
@interface RestorableViewController () <UIViewControllerRestoration>

@end

@implementation RestorableViewController

- (id)initWithNibName:(NSString *)nibNameOrNil
               bundle:(NSBundle *)nibBundleOrNil
{
    self = [super initWithNibName:nibNameOrNil bundle:nibBundleOrNil];
    if (self) {
        self.restorationIdentifier = NSStringFromClass([self class]);
        self.restorationClass = [self class];
    }
    return self;
}

#pragma mark - State Restoration

+ (UIViewController *)viewControllerWithRestorationIdentifierPath:(NSArray *)identifierComponents
                                                            coder:(NSCoder *)coder {
    return [self new];
}

@end

One sticking point that gets me every time I create a new UITester target: you must explicitly declare that you implement the UIViewControllerRestoration protocol. Just implementing the proper methods is insufficient and if you do not declare this than state restoration will silently and confusingly fail.

I hope this was helpful. Setting up a new target like this has certainly made developing new interface elements more straightforward for me.

Catch Implicit Self Retains

Who hasn’t run into this issue?

1
2
3
4
5
6
7
@synthesize array;

- (void)captureArray {
    self.block = ^void() {
        NSLog(@"%@", array);
    }
}

Yeah. The reference to the array iVar will implicitly retain self and boom baby you’ve got a memory leak. Granted, only a monster would call @synthesize array, but we’ve all used code written both those less competent than us. And maybe you’re feeling lazy that day and decide to directly reference a property’s backing iVar instead of going through self and than you don’t notice that you forgot to declare weakself outside the block.

It happens to the best of us.

Well fret no more. Thanks to sharp eyes of Peter Hosey, we are now aware of a warning you can enable in Xcode that will notify you any time you implicitly retain self. Set CLANG_WARN_OBJC_IMPLICIT_RETAIN_SELF = YES in your xcconfig (or in the build settings of your project), and you’ll be notified the second you accidentally retain self.

I’m Learning Android Dev

It’s about time I took a look and saw how the other half lived. I’m learning Android development. I bought the BNR Android book and have started working my way through the chapters. Keeping in mind I’ve only been doing this for two or three days, here are my thoughts:

  • Big Nerd Ranch writes exceptional books.
  • The Android Emulator is slow. It’s like DMV slow.
  • I’ve spent a surprising amount of time cleaning builds and restarting Eclipse and the emulator. I wouldn’t expect to get into that kind of debugging so quickly, especially on such a simple project. And while I’m complaining about Eclipse, non of their image assets are Retina. Since this is the only non-retina app I’ve used in a while, the appearance is strikingly bad.
  • String handling in Android is much better than in iOS. Has anyone written anything similar for iOS? Checking the googles…
  • I haven’t used Java since 2006 or 2007. It was surprisingly easy to pick back up.

I realize that my complaints about Eclipse and the emulator can be fixed by switching to a different IDE and using alternate emulators, but I’m making a conscious effort to learn the official way to develop Android apps before I strike out on my own and customize my own environment.

Waterfield Designs Staad Backback

Just a few weeks ago Waterfield Designs released their first pack, the Staad Backback. Strangely enough, every review I’ve seen is just a regurgitation of the press release and the product page, so I thought I’d give a little write-up after actually handling the pack.

First, my current backpack is the Tom Bihn Smart Alec. This is the best backpack I have ever owned. It’s comfortable, it’s durable, it’s sufficiently waterproof to ride my bike to work in a downpour. It has the most usable pocket system I’ve ever seen in a backpack. It’s also a bit big for what I need day-to-day, so I’ve been casually browsing around for a something smaller to get me back and forth to work.

After seeing my at the Staad, I decided to go with the waxed canvas, chocolate leather slim version of the bag. I went back and forth on the sizing, but I currently have a 13” laptop and a bag big enough to haul groceries in, so if I’m going to buy a new bag I might as well go with the smallest bag that’s useful.

First Impressions

As I write this, I have just recived the pack, so I don’t have any real usage notes to report. Here are my first impressions; things that I was wondering about, I’ve seen people ask about or details that surprise me.

The buckle is not vintage. Every review I’ve read mentions the “vintage” buckle. I think what they mean is it is a “vintage style” buckle. The buckle itself is brand-new and plastic. That being said, it’s an interesting buckle. If you watch Gary’s video notice how smoothly he opens the flap. It really is that smooth. The video glosses over the closing action a bit and makes it hard to see the exact mechanism for closing the bag. When you want to close the bag, you push the main tab down, then manipulate the small plastic bit through the slot. On a brand new Staad this is easy, as the stiffness of the webbing and the leather tab keeps everything in place and ready to close. I’m interested to see how this changes as the bag ages and everything breaks in.

Here are some animations illustrating the opening and closing action:

opening the clasp closing the clasp

This clasp is fun to operate. It is one of the most satisfying closures I’ve used, rivaling the feeling you get when you rip open the fly on old broken-in button fly jeans.

The outside pockets are small, best suited to thin objects. I’ve got medium sized hands, the pockets are almost the exact size of my hands. Too small for a Moleskine, just right for Field Notes. You aren’t going be fitting a water bottle in here. These pockets are best suited for small items, earbuds, wallets, notebooks, gum, etc. Because of the stiffness of the waxed canvas, the pockets don’t stretch or deform, so you aren’t going to be able to cram a lot of stuff in there even if you wanted to.

I didn’t notice this in any images or descriptions, but the laptop and iPad pockets have a very nice fleece lining. The iPod pocket is thin, just big enough for a bare iPad (I couldn’t put my iPad mini + cover in the pocket without the cover sliding off).

I had two bottles of wine in the house. Both fit into the main compartment easily and I think I could have fit a third in there. This assumes that none of the other pockets have anything bulky in them. The pocket tapers towards the top, so putting the wine in requires unzipping the zipper. Once zipped it is fairly secure and the wine doesn’t fall out even when the bag is inverted. There’s no way you could fit a six-pack without taking the bottles out of the carrier.

The main compartment won’t fit anything much bigger than a long-sleeved t-shirt. Pack light.

The underside of the flap is black leather.

Zipper pulls are generic plastic pulls. They’re fine, same pulls my Tom Bihn bag uses. I wish bag makers like Waterfield Designs and Tom Bihn would use something a little nicer, though.

Laptop sleeve ends about 2 inches above the bottom of the bag. You’d have to set the bag down very hard to have the laptop bump.

The interior pockets close with Velcro, but it’s a nice Velcro. The loop part is tight, the hook part is not rough or scratchy; it’s almost smooth. The pockets are not deep. A Field Notes notebook sticks up enough that the velcro closure cannot close.

This is probably obvious to everyone considering this bag, but it’s worth being explicit: this bag is going to get a worn look very quickly. The leather flap already has scratches on it from me opening and closing the clasp. The waxed canvas has some scuffs. Anyone considering buying this bag probably desires the broken-in look, but if you like your gear to keep looking pristine, this is likely not the bag for you.

Amend Files to Previous Commit

I run into this frequently when doing big a big refactor. I’m carefully committing my changes in nice bisectable units, but then Woah! there’s a change that should be included in a previous commit. Here’s how you fix this up in Git.

Disclaimer: We are modifying Git history. Do not do this if you have already pushed these changes.

$ git log --oneline

39e1678 Removed allowsAirPlayVideo method
6c750a1 Removed UILineBreak enums
ce2c34f Removed all UITextAlignment enums
a5c04ad Remove dispatch_release() calls
8681487 Removed Refresh Header

There we go. My current changes should be included in commit 8681487, “Removed Refresh Header”. Fixing this is easy. Add your changes to the staging area, then run:

git commit --fixup=8681487
git rebase --interactive --autosquash 8681487~1

The first command commits your changes, but modifies the commit message to be the same as 8681487 with “fixup!” appended in front. Running rebase in interactive mode with “autosquash” turned on will move our previous commit right after the commit we’d like to modify and update that commit with our new changes.

Easy as pie!

Debugging Smashed Memory in Obj-C

We were getting a crash inside a button. Calling po self wasn’t helpful.

(lldb) po self
$1 = 0x0ce854d0 [no Objective-C description available]

Well.. That’s weird. I wonder what’s at that memory location?

(lldb) memory read 0x0ce854d0
0x0ce854d0: 00 00 00 b0 93 6a ce a0 0e 00 00 00 00 00 00 00  .....j..........
0x0ce854e0: 10 c7 e7 0c 00 00 00 00 00 00 00 00 00 00 00 00  ................

That… doesn’t look right. Let’s turn on some debugging tools and see if that helps. Open the ‘Edit Scheme’ window and navigate to the Diagnostics tab. You’ll want to turn on “Enable Scribble” and “Malloc Stack”. You can read more about these methods here, but in short, “Enabled Scribble” will cause the allocator to write 0xAA to newly allocated memory and write 0x55 to deallocated memory. “Malloc Stack” will log the allocation and free history of your memory.

debugging settings

Let’s get our app to crash again and see if that helped.

(lldb) po self
$1 = 0x0cdcd2d0 [no Objective-C description available]
(lldb) memory read 0x0cdcd2d0
0x0cdcd2d0: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU
0x0cdcd2e0: 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55 55  UUUUUUUUUUUUUUUU

Well, there we go. Obviously someone else is freeing self while we’re in the middle of a method. Let’s grab the PID of our crashing process. Easiest way to get this from an iOS app is to check out any log statements in the terminal.

2013-04-22 10:59:38.194 Sing![14105:2203] Loggin'
                           PID^^^^^

Mosey on over to your trusty terminal and let’s see what’s happening at that memory address.

$ malloc_history 14105 0x0cdcd2d0

This is going to fill your screen with a massive spew of text. You’ll probably want to pipe the results to your text editor of choice. The important bits are right there at the top, though. Check it out:

ALLOC ... 
----
FREE  0xcdcd2d0-0xcdcd3a7 ... CFRunLoopTimerInvalidate | _timerRelease | ... -[SongPreviewButton dealloc] ... free 

About 100 lines of junk omitted. But there you go. We’ve got a timer that’s holding on to a button, preventing it from being freed when it should be, then all of a sudden the timer lets go and everything falls apart. Simple!

List Rake Tasks by Default

I add this to all my Rakefiles.

1
2
3
task :default do
  system "rake --tasks"
end

It prints a list of Rake tasks when you run Rake without a command. Not only does it help you remember what options are available in the current project, but it keeps you from accidentally performing some task if you fat-finger the rake command.

Unit Testing Parse Cloud Code

Like many people, I was thrilled when Parse announced their cloud code product. I’ve just started a little iOS project that required both persistent cloud storage and pulling data from a 3rd party API. Since the API had a great JavaScript library, but no built-in Obj-C support, moving the code onto the server had some big benefits: greatly simplified networking in iOS, allowed me to reuse the 3rd party library as is, and decreases my turnaround time should I need to modify this code in the future.

Now, I’m usually not a strict test driven developer, but these cloud code modules are a different story; the code is running on a server and accessing a 3rd party API. In this situation, quick build/test/debug cycles are impossible and testing is the only way go.

Here’s how I set up my testing environment. Please keep in mind that this is the first time I’ve used Node.js, first time I’ve written unit tests for JavaScript and the first real JS project I’ve worked on. In fact, before this, the only JS code I’d written was hackly little Safari extensions, so this is a whole new world for me. I’m writing this for someone with experience similar to mine; if you are experienced with Node, feel free to skip ahead.

Setting up the test environment

I assume you’ve already got Node and npm installed. If you don’t, they both can be installed via Homebrew.

I used Mocha.js for the testing framework and Expect.js for assertions. Mocha supports any assertion framework you can throw at it. Expect seems to work well and doesn’t generate Lint warnings like Should.js. Run the following commands from your project directory.

$ npm install mocha
$ npm install expect.js

These commands install the mocha and expect frameworks in the local node_modules directory. This greatly simplifies your environment. Code can be shared between collaborators without worrying about what framework version each dev has installed.

At this point, your Parse directory should look like this:

cloud /
  main.js
config /
  global.json
node_modules /
  .bin /
  mocha /
  expect /

Creating Cloud Code Modules

We’re all set to test, but first we need something to test. We’re going to add some code that just returns a helpful message. Modify main.js to look like so:

1
2
3
4
5
var message = require('cloud/message.js');

Parse.Cloud.define("get_message", function (request, response) {
  message.getMessage(request, response);
});

What I’ve done is load each Cloud Code function from a separate module, this worked well for me because each function is independent of all other functions, but YMMV. Let’s setup some code to test. First, create a file named message.js in your cloud directory. Now modify it to look like so.

1
2
3
exports.getMessage = function (request, response) {
  response.success("Good job, buddy");
};

A bit about how Node.js loads modules, since this was all new to me. When each module is loaded, there is an object created called exports that is available within that module. Any function attached to that object will be available externally when your module is loaded. So in this example, our message module creates one function called getMessage. When we call var message = require('cloud/message.js'); the object returned from the require() function is that exports object.

Creating Tests

Now let’s create some tests. First, the default directory for Mocha tests is test, so let’s put our test there. Create the test directory and put a file in there named, “messageTests.js”. Modify it to look like this:

1
2
3
4
5
6
7
8
9
10
var message = require('../cloud/message.js');
var expect = require("expect.js");

describe('Message', function () {
  describe('response', function () {
      it('should return the correct message', function () {
          expect().fail("No tests yet");
      });
  });
});

First we import our message and expect modules. The describe() function is used to define the scope for associated tests. The it() function defines a Mocha test. Let’s run our test.

$ node_modules/.bin/mocha 

Notice that the error message says, “Message response should return the correct message:”, so structure your describe and it messages to make that message nice and readable. Let’s replace our failing test with an actual tests.

1
2
3
4
5
6
7
8
it('should return the correct message', function (done) {
  message.getMessage({}, {
      success : function (message) {
          done();
          expect(message).to.be.eql("Good job, buddy");
      }
  });
});

There’s a few things to notice here. First, the done() function is an optional parameter to the describe() and it() methods. Any tests within will not complete successfully until the done() function is called, so you can use it to test callbacks and ensure that they were called. Second, notice the format of the expect() function. You can read the documentation for more details, but in general, the tests always follow this form, beginning with an expect() function and ending with a function.

Run the tests again and success! All our tests pass. All in all, it took me less than a day to try out different testing and exception modules, settle on Mocha and Expect, then write enough tests to nearly fully cover the Cloud Code I had written. Coming from Objective-C, the power and flexibility of JavaScript amazes me. Writing these tests was almost a joy.

JSLint: Expected ‘Return’ at Column X, Not Column Y

I’ve been writing some Javascript using the default settings in Chocolat, tabs instead of spaces and each tab is equivalent to 2 spaces. Running most of my javascript files through JSLint is fine, but there were a few lines that were generating warnings, even though the spacing looked just fine.

if (validateCardRequestDidSucceed(stripeResponse) === false) {
    response.error("Stripe card request failed with unknown error");
    return; // Expected 'return' at column 17, not column 19.
}

What’s wrong here? That spacing looks just fine to me. Turns out that the default settings in JSLint want spaces instead of tabs and 4 spaces per indentation. JSLint, by default, ignores tabbed indentation, but somehow that return had been indented with spaces.

Replacing the spaces with tabs cleared up the issue.

In other news, I should probably switch to 4-space indentation. I’m not picky about spacing and, all things being equal, I might as well stick with the JSLint conventions.