How to Create Fixture Files for Unit Tests

This is mostly a reminder for my future self: It doesn’t suffice to create a TXT file and add it to the target in the file inspector (⌘⌥1) to be able to read it as part of the bundle. You also have to drag it into the “Copy Bundle Resource” build phase of the target so it get, well, bundled into the product. (In my case, it was the test target.)

screenshot of Xcode
The .md file was part of the test target but loading it from the NSBundle failed until I added it to the proper Build Phase
  1. Create an empty file or add an existing file to the target’s group in Xcode and make it part of the proper target,
  2. drag it into “Copy Bundle Resources” build phase,
  3. load it using NSBundle(forClass: TheTestCase.self).URLForResource("filename", withExtension: "txt").

Storing PLIST or JSON files for structured data works just as well. I happen to require plain text flavors most of the time and always wonder why the loading fails for a couple of minutes.

Reusable View Components from Nibs

Just found this today in a Slack channel. It seems we can actually reference and re-use Xib files by overriding awakeFromCoder!

If we are loading from placeholder view, we create a real view and then we transfer some common properties from it and all it’s subviews, then we just return that instance in place of placeholder, otherwise we just return normal view (This method is implemented on NSObject so we can call super, but this still should be done with method swizzling instead of category smashing).

There’s a sample project on GitHub. Let’s tear it apart.

It works like this:

const int kNibReferencingTag = 616;

@implementation UIView (NibLoading)
// ...
- (id)awakeAfterUsingCoder:(NSCoder *)aDecoder
{
  if (self.tag == kNibReferencingTag) {
    //! placeholder
    UIView *realView = [[self class] loadInstanceFromNib];
    realView.frame = self.frame;
    realView.alpha = self.alpha;
    realView.backgroundColor = self.backgroundColor;
    realView.autoresizingMask = self.autoresizingMask;
    realView.autoresizesSubviews = self.autoresizesSubviews;

    for (UIView *view in self.subviews) {
      [realView addSubview:view];
    }
    return realView;
  }
  return [super awakeAfterUsingCoder:aDecoder];
}

When the kNibReferencingTag is set, the current instance (self) is treated as a prototype. From that prototype we transfer common properties to the realView which is properly loaded from a Nib. That means it doesn’t go the kNibReferencingTag path but the usual path, deferring to super.

The sample app contains SomeView with its own Xib that should be reused.

In the app’s Xib, we have a scene that uses it as follows:

<scenes>
    <!--View Controller-->
    <scene sceneID="4">
        <objects>
            <viewController id="2" customClass="ViewController" sceneMemberID="viewController">
                <view key="view" contentMode="scaleToFill" id="5">
                    <rect key="frame" x="0.0" y="20" width="768" height="1004"/>
                    <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                    <subviews>
                        <view tag="616" contentMode="scaleToFill" id="VTu-Cz-9kE" customClass="SomeView">
                            <rect key="frame" x="113" y="216" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                        <view tag="616" contentMode="scaleToFill" id="7te-Q6-moz" customClass="SomeView">
                            <rect key="frame" x="199" y="446" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                        <view tag="616" contentMode="scaleToFill" id="7vx-xh-xRD" customClass="SomeView">
                            <rect key="frame" x="375" y="231" width="100" height="100"/>
                            <autoresizingMask key="autoresizingMask" widthSizable="YES" heightSizable="YES"/>
                            <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                        </view>
                    </subviews>
                    <color key="backgroundColor" white="1" alpha="1" colorSpace="custom" customColorSpace="calibratedWhite"/>
                </view>
            </viewController>
            <placeholder placeholderIdentifier="IBFirstResponder" id="3" sceneMemberID="firstResponder"/>
        </objects>
    </scene>
</scenes>

I know, Xib files aren’t the best to read. Here’s what it boils down to:

  • Create a scene using a view controller of type ViewController.
  • In its main view place 3 subviews …
    • of type SomeView,
    • all with the tag 616,
    • and a few standard color properties – apparently all set to white. It doesn’t matter anyway since the SomeView.xib will dictate what it really looks like.

Unlike @IBDesignable components, you won’t have any live preview in Interface Builder. Just empty placeholder boxes.

iRamDisk May Speed Up Your Xcode Compilation Times

Teaser image

I code on a late 2011 Mac Mini with 8 GB RAM and a 256 GB SSD. This machine is a ton faster than my old MacBook Air was. Compilation still takes time, but it seems that iRamDisk helps a bit.

Lately I wondered if I could cut down the 30s compilation time (3mins with a clean build folder) if I had a Mac Pro, or MacBook Pro, or iMac, or whatever next tier device. Faster cores, more cores, doesn’t matter. But buying a Mac for $3k is out of question at the moment. So I’ve been looking for other tricks.

The only thing that’s faster than a SSD is RAM. That’s when I found the app iRamDisk. It offers an option to move the derived data folder to a virtual disk in RAM. It seems I can reduce the clean build time from 3mins to 2mins with that. Xcode needs about 1.5GB derived data for the Word Counter – at least that’s how big I had to make the RAM disk to not get filled quickly. The overall memory pressure is a bit higher, the Mac is using swap more, but compilation becomes faster at last.

There’s a downside, too: after every reboot the RAM disk is empty, so Xcode has to index the project again and compile fresh at least once a day. Depending on your usage this can be annoying or not be a problem at all.

You can download a trial from the website or buy it for $19.99 on the Mac App Store.

Don't Build on El Capitan Without Checking App Transport Security

I got burned this week. Pretty bad. I shipped a small bugfix release for my Mac app Word Counter a couple of days ago to prepare for the “big one” coming this week. Naturally, I built that version on my El Capitan dev machine. I pushed the update to my server. Updates using Sparkle worked. – But now users of that version cannot ever update to the next version. Because I haven’t thought about ATS.

Continue reading …

Make Custom Debug Build Configurations Play Nicely With CocoaPods

To test the Word Counter during development, I have long used a special build target. But that doesn’t scale well if all I want is change a preprocessor macro to switch from file-based to in memory storage, for example. I’ve never played around with build configurations in Xcode. They work well with Schemes, though, and setting up a build configuration and a scheme is much less overhead than maintaining a custom target.

Continue reading …