Guide: Up and Running with Kiwi

PaulSolt edited this page Dec 2, 2012 · 42 revisions

This guide is meant to be a gentle introduction to setting up Kiwi and static libraries in general for use in your own projects. If you know what you are doing, follow the Condensed Guide. In the Extended Guide, we will go into excruciating detail and fix common build problems as they arise for instructive purposes.

Condensed Guide

  • Add a test target to your app project.
  • Bring in the Kiwi project into your workspace to make the libKiwi.a static library available.
  • Make sure spec/test files are added only to the test target.
  • Add the Kiwi headers directory to your User Header Search Paths of the test target.
  • Link the test target with the Kiwi static library.
  • Add the -all_load flag to the Other Linker Flags of the test target.

Extended Guide

We will start from scratch by setting up an iPhone project that is built with ARC, includes a test target, and is linked with a Kiwi static library.

This guide assumes and uses screenshots of Xcode 4.2 for illustrative purposes. Also, I expect that you will be using Clang as the compiler Xcode is using throughout. If you are running Xcode 4.2, this should already be the case.

The name of the sample project in the guide below will be PhotoSection, but it should be trivial to adapt for your own use.

1. Creating and Examining a New Project

  • Create a new master detail iPhone project in Xcode 4.2, and call it PhotoSection. Make sure that the Use Automatic Reference Counting and Include Unit Tests options are checked during the project creation phase.

1

  • Click on the PhotoSection project in the Project Navigator on the left side of Xcode. We can see that Xcode has created an app target called PhotoSection and a test target called PhotoSection Tests.

2

  • Xcode also added starter test files called PhotoSectionTests.h and PhotoSectionTests.m. As you can see, I also did some tidying up of the project groups in the project navigator.

3

4

  • Click the PhotoSection app target and look through its build settings. The target is built with ARC (Automatic Reference Counting) enabled. Kiwi is not written to use ARC internally, but your own projects can be ARC enabled and link to a Kiwi static library without problems.

5

  • Run the Test action through the Product menu item, or by using Cmd-U. It works fine although we get alerted to a failing test in PhotoSectionTests.m.
  • This shows that the test target is working fine, so lets make a quick fix as in the image below to get the test passing. Once you have made the change below run the Test action again to verify the issue has been fixed.
  • We now have an iPhone project with a working test target. Time to move on to Kiwi.

6

2. Adding Kiwi to the Project

  • The best way to use Kiwi in your project is to set up an Xcode workspace that contains both your app project and the Kiwi project, which is what we will guide you through.

  • add the Kiwi project into the ./Frameworks/Kiwi subdirectory of your existing app. If your project uses Git for version control, you can use submodules to make updating in the future easier:

      cd /path/to/MyApplicationSource
      mkdir Frameworks
      cd ..
      git submodule add https://github.com/allending/Kiwi.git Frameworks/Kiwi
    

If you're not using Git, simply download the source and copy it into the ./Frameworks/Kiwi directory.

  • Drag the Kiwi.xcodeproj file from OS X Finder directly into Xcode's Project Navigator.

7

  • Xcode will prompt you about creating a workspace. Accept, and create the workspace file somewhere that makes sense. For the example in this guide, we have saved the workspace file in the same directory as the project file.

8

  • Once the workspace has been created, you should also also see Kiwi in the project navigator.

9

  • Click on the Kiwi project in the Project Navigator. Then, examine the Kiwi target (you can ignore the KiwiTests and KiwiExamples targets). You will be able to see that the Kiwi target builds a static library with ARC disabled.

10

  • Make sure that the active target in Xcode is PhotoSection > iPhone (some version) Simulator. This should already be the case, but check anyway because adding Kiwi to the workspace would have caused more targets to become available.

11

3. @try-ing to Use Kiwi

  • First, a note. There are a number of configuration issues involved when using Kiwi. For instructional purposes, this guide purposefully fixes these issue only as they are encountered to simulate the typical problems many people face when setting up libraries like Kiwi for iOS projects.
  • Now that we have Kiwi in our workspace, let's create a Kiwi spec (or test) file.
  • Create a new empty file called MathSpec.m. I recommend using the Other->Empty file template to avoid the noise present in the other file templates. Note that you do not need a .h file because the spec will be completely defined in the .m.
  • It is neater if MathSpec.m is created in the PhotoSection Tests group in the Project Navigator.
  • Importantly, make sure that during the file creation phase, MathSpec.m is added to the PhotoSectionTests target, and not the PhotoSection target. Every spec/test file you ever create should only ever be added to test target, or the compiled source for the spec will end up in your app!

12

4. First Problem - Missing Headers

  • In MathSpec.m, add the line #import "Kiwi.h" at the top. This is a convenience header that makes all the Kiwi class, function, and macro declarations visible.
  • Try running the Test action through the Product menu item, or by using Cmd-U like before.

13

  • It fails because we are trying to #import "Kiwi.h", but for the current active target PhotoSection, no such file is visible to the compiler. We are going to have to tell it where to look.

14

  • Click on the PhotoSection project and the PhotoSectionTests target and bring up its build settings.
  • Look for the User Header Search Paths row, and add the directory $(SOURCE_ROOT)/Frameworks/Kiwi/Kiwi
  • Try running the Test action again. It should succeed without issues this time because Kiwi.h is now visible to the compiler. You should also see some console log output about the test run.

Suggested Edit/Fix: When I follow along this alone won't find the headers. Only after I add the static lib below and thus cause the building of Kiwi when I hit command-u will it work. what about setting search paths to the directory Kiwi is in? If you have any spaces in your path to $(SOURCE_ROOT) you need to put the above command in quotes "$(SOURCE_ROOT)/Frameworks/Kiwi/Kiwi"

15

5. Second problem - Undefined Symbols

In Progress

  • Add the following code to the almost empty MathSpec.m file. It declares and defines a spec which does not have any actual examples/tests.

      SPEC_BEGIN(MathSpec)
    
      SPEC_END
    
  • Run the Test action again. Oops, we seem to have another build failure.

16

  • Click on the Xcode Issue Navigator (the fourth icon on the left pane). We see it complaining about undefined symbols (_OBJC_METACLASS_$_KWSpec", referenced from: ...).
  • The problem is the test target has been compiled, but during the linking phase the source that the SPEC_BEGIN(MathSpec) and SPEC_END macros expands to compiles into object files that have to be linked against symbols in the Kiwi static library, but the linker cannot find them.
  • What we did earlier made the Kiwi headers available to the compiler, but we also need to link the target to the Kiwi static library.

17

  • Open the PhotoSectionTests target again. This time, open the Build Phases tab.
  • libKiwi.a needs to be listed in the Link Binary With Libraries table but it is not.
  • Click the + symbol, search for libKiwi.a, and add it. Note that the reason libKiwi.a is listed here is because we added the Kiwi project to the workspace and Xcode sees that the Kiwi project has a target that builds a static library.

18

  • A libKiwi.a item should also show up in the table and in the Project Navigator.
  • You can drag the libKiwi.a item in the Project Navigator to a group that pleases you like I have.

18

  • Run the Test action again. Success! We are almost done.

6. Final Problem - Missing Category Methods

  • Fill in the MathSpec.m file with the contents below.

      #import "Kiwi.h"
      
      SPEC_BEGIN(MathSpec)
      
      describe(@"Math", ^{
          it(@"is pretty cool", ^{
              NSUInteger a = 16;
              NSUInteger b = 26;
              [[theValue(a + b) should] equal:theValue(42)];
          });
      });
      
      SPEC_END
    
  • Run the Test action like before.

  • We don't get a build error now, but the test runs and fails when it seems like it should pass.

19

  • We will use the Log Navigator to figure out what went wrong. Click on the Xcode Log Navigator (the last icon on the left pane) and the select the top item in the navigator, which should be Test PhotoSectionTests.
  • This brings up the log for the latest test run.
  • It tells us that the test failed because of an NSInvalidArgumentException ... unrecognized selector sent ....
  • The problem this time is that Kiwi uses Objective-C category methods extensively and during the linking phase, the linker omitted Kiwi symbols that appeared to be unused from the binary.
  • Fixing this problem requires another visit to the test target build settings.

20

  • Open up the build settings of the PhotoSectionTests target.
  • Look for the Other Linker Flags field and fill it with -all_load. This will force the linker to load every object from every library it sees, which in our case means that everything from libKiwi.a will be loaded into the target binary.

21

  • Try out the Test action for a final time.
  • The spec should run and pass. Everything finally works.
  • Writing good specs or tests, another matter entirely.

22