How to Build the Facebook Paper Status Bar Hover

paper

Among the many great little design details in the new Paper by Facebook app released last week, this status-bar-hover thing caught me by surprise. My first reaction was “Hey, they can’t do that!”, but of course (and to quote my favorite line from Independence Day) well they just eh… did.

After a little digging around, I’ve figured out how to do it and it involves using multiple UIWindow instances. I’ve always thought that iOS applications could only ever use one UIWindow, but that turns out to be not the case. It’s perfectly alright to have more than the [UIApplication sharedApplication].keyWindow which you usually create in the AppDelegate (or Storyboard creates it for you).

A UIWindow is just a subclass of UIView, but it’s also a special type of view that’s specifically for providing an area for displaying views and for distributing events to those views. A UIWindow instance has a property called windowLevel that allows you to specify where on the z-index the window appears relative to other windows in the app. Most of the time you only have your main window with a windowLevel set to UIWindowLevelNormal, and then occasionally a UIAlertView window is displayed with a windowLevel of UIWindowLevelAlert.

So to create a new UIWindow and have it’s contents appear above the status bar, all you have to do is this:

1
2
3
4
5
6
UIWindow *foregroundWindow = [[UIWindow alloc] initWithFrame:[[UIScreen mainScreen] bounds]];

foregroundWindow.backgroundColor = [UIColor clearColor];
foregroundWindow.rootViewController = [ForegroundViewController new];
foregroundWindow.windowLevel = UIWindowLevelStatusBar;
foregroundWindow.hidden = NO;

That will display the contents of ForegroundViewController on top of the status bar. I’ve put together a demo app with the above technique (combined with a sprinkle of a pan gesture and dynamics) that looks like this:

demo

Download the project over at github.

Gotchas

The demo I built is probably not the end of the story. Check out Shaun Ervine’s post on using multiple UIWindow instances for some possible issues / gotchas in using this technique.

Building Better Transitions With iOS 7

I gave my first iOS related tech talk yesterday at Alt Tech Talks London, which was a blast, especially to share the stage with such accomplished people in the iOS community.

As I said in my talk, transitions are important, and the flexibilty brought on by the opening up of the transition system in iOS 7 has created some opportunities for developers to make their apps standout and provide a better experience for their users.

Ironically, I built my presentation as a series of videos, animations, and transitions, and so it doesn’t really make sense to post the slides as a flat PDF. Instead I’ve posted an Xcode project that includes all the code so that you can open it up and fiddle around with it, read the comments, or use it as a basis for transitions in your own apps. Here is the final product of a customized modal transition:

Example Custom Modal Transition in iOS 7 from Eric Allam on Vimeo.

Check it out on Github or Download the ZIP.

Easy Markdown Rendering With NSAttributedString on iOS 7

A little known addition to iOS 7 makes rendering markdown to a UITextView really simple. The UIKit Additions to NSAttributedString now includes a document type option called NSHTMLTextDocumentType that does exactly what you’d expect: it allows you to easily render HTML in a UITextView, UILabel, or UITextField. So if we combine the new document type with a markdown parser, we can go from this:

1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
A First Level Header
====================

## A smaller header

**Now** is the time for all *good men* to come to
the aid of their country. This is an `NSAttributedString`.

Brought to you by [Eric Allam](http://twitter.com/eallam)

### Header 3

*   Candy.
*   Gum.
*   Booze.

![eallam twitter profile](https://si0.twimg.com/profile_images/3066111745/97865436e3ef039bc7c2420fe5be366e.png)

To this:

Alt Text

With only a couple of lines of code.

First, you need a markdown parser which will take a markdown formatted string and turn it into HTML. For this example we are going to be using MMMarkdown.

MMMarkdown makes it extremely simple to turn some markdown into HTML. If we had the markdown above in a file called Example.md in our project, you can turn it into HTML like so:

1
2
3
NSString *markdown = [NSString stringWithContentsOfFile:[[NSBundle mainBundle] pathForResource:@"Example" ofType:@"md"]  encoding:NSUTF8StringEncoding error:nil];

NSString *html = [MMMarkdown HTMLStringWithMarkdown:markdown error:nil];

Then, once you have the HTML, just create the NSAttributedString like so:

1
2
3
NSDictionary *options = @{NSDocumentTypeDocumentAttribute: NSHTMLTextDocumentType};

NSAttributedString *preview = [[NSAttributedString alloc] initWithData:[_html dataUsingEncoding:NSUTF8StringEncoding] options:options documentAttributes:nil error:&error];

Now all you have to do is set the attributedText property on a TextKit backed view (e.g. UITextView), like this:

1
2
UITextView *liveView = [[UITextView alloc] init];
liveView.attributedText = preview;

This doesn’t mean the UITextView can display all the HTML you throw at it. Stylesheets have no effect (although certain CSS styles do seem to work, but it’s not documented anywhere what is supported and what is not). If you do want to display a full web page, you could of course always use UIWebView instead.

I’ve uploaded an example project that demonstrating how to put this all together called MarkyMark (the naming of this repo happened to coincide with a viewing of Pain and Gain).

Breaking Bad With DTrace

If you have any feedback on this article, please contact me on twitter

I’ve spent an unwise amount of time recently on a problem that arose when me and my Code School colleagues were developing the challenges for our upcoming course on MapKit. All of the challenges assume that the user has given the app permission to use it’s current location, and our KIF tests in the simulator wouldn’t work unless we could somehow programmatically confirm this alert box:

KIF tests run in the simulator and are built to a different target, so using private API’s isn’t a problem (KIF wouldn’t work unless it used a ton of private API’s). Jim Puls from Square (the makers of KIF) was helpful enough to chime in this thread to share how they do it at Square: by method swizzling the crap out of the CLLocationManager class, replacing startUpdatingLocation, location, and locationServicesEnabled with their own versions so the user location mechanics would be wholesale replaced, thus getting around the permission alert box.

We followed their advice and ended up mocking out CLLocationManager (see how in this gist) and it worked well enough, but I was unsatisfied that we had to mock out the entire location machinery just to get rid of that permissions alert box. It wasn’t elegant code.

…perfection is finally attained not when there is no longer anything to add, but when there is no longer anything to take away…

I decided to keep searching for a more elegant solution and I started at what I thought was the most obvious place: UIAlertView.

Searching for UIAlertView

If I could find the code where the offending UIAlertView is actually created then I would know which code to mock out and hopefully bypass permissions. To do this, I could have swizzled some UIAlertView init methods or added a symbolic breakpoint in Xcode, but I had recently come across Mark Dalymple’s excellent three part series on DTrace (1, 2, and 3), and this seemed like a good opportunity to use it for a worthy real-world problem.

I created a new blank iOS 6.0 project with a single MKMapView that wants to show the current user location (you can ⬇download the project here). I built and ran the app for the simulator to verify that it brought up the alert box and to create a binary that I would later use in Instruments as a target for a custom DTrace instrument.

location alert

Instruments is powered by DTrace and by using it it made a couple of things easier, like launching an app in the simulator as it attached DTrace probes and logged the results, as well as a cleaner interface for viewing call stack information. To create custom DTrace probes in Instruments, start by opening Instruments from Xcode:

open instruments

And then create a new blank document:

blank document

Use ⌘B to build a new instrument, and you should come across this screen:

new instrument

Which presents a nice interface for creating custom DTrace scripts. To find all methods (class or instance) called on UIAlertView, I ended up with this:

uialertview

The part to pay attention to is this group of boxes here:

group

Next up I needed to the choose the target this instrument would run against

target

You have to pick the executable that was built for the simulator, which you can find in ~/Library/Application\ Support/iPhone\ Simulator/6.0/Applications/. In there you might see many directories with randomly generated names:

rando

You’ll have to dig through the noise to find the executable you want:

noise

Now all that’s left is to hit the record button and hope we can find out where that UIAlertView is being initialized:

As you can see, there were 3 UIAlertView method calls that all came from [UIWindow keyWindow], and one from a performSelector, but that doesn’t help us much. Let’s update that probe to record both the module (in this case the class name), and the name of the method

adding information

Now it’s a little easier to see what’s going on. It looks like [UIWindow keyWindow] calls private class method +_alertWindow on UIAlertView.

private

Could this be where our location permissions alert box is being created. Fortunately, our instrument’s probe automatically records the stack trace information for each of the events recorded. To view the stack trace information, we just need to select an event and open the right hand side drawer:

stack trace

The stack trace of the _alertWindow calls are all the same, and lead to a dead end. They don’t seem to be related to location at all but instead are triggered on normal app startup routines. The only other hit we got, +_initializeSafeCategory, is related to Accessibility and not location.

This is a dead end.

Well, not exactly. Using DTrace I was able to eliminate the possibility that the UIAlertView was created inside the TestingCurrentLocation process, which means it has to be created in another process. So I knew that somehow, my TestingCurrentLocation process was communicating with another outside process which was responsible for location permissions. Apple doesn’t want to give app developers the chance of getting around the location permissions box for privacy reasons, so they would want to lock it down in another process.

The Mystery Process

So my next goal was to figure out what this mystery outside process was. I knew that my app process and the mystery process had to communicate, which led me to research the XPC Services API which “provides a lightweight mechanism for basic interprocess communication integrated with Grand Central Dispatch (GCD) and launchd” and is an integral part of App Sandboxing, so it seemed like an interested place to start. I tried logging all methods called on parts of the Objective-C API, like NSXPCConnection, and NSXPCInterface, but there was nothing there. The next most obvious thing to probe was the c API, specifically the xpc_connection_create function. Here is how I created the probe I to log all the calls to xpc_connection_create with the caller and the name of the service with which to connect:

As you can see, probing this function turned out to bear some real fruit. It found a call to xpc_connection_create that was creating a connection to something named com.apple.locationd.registration and the call stack confirmed that this being triggered by setting the map to display the users location:

xpc_connection_create results

Running sudo ps aux | grep locationd showed that their was indeed a locationd process running in the simulator located at /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec/locationd (there was also one running at /usr/libexec/locationd which is the location daemon for Mac OS X.)

locationd

This gave me a new process to probe for information. But what should I look for? I knew that if a user allowed an app in the simulator to get their location, they wouldn’t be asked again even if the simulator was restarted (only by resetting the simulator would the location permissions alert box come up again). So I knew that there had to be somewhere on the filesystem where locationd was storing the permission authorizations for simulator apps. If I could find this file (most likely a preferences file), I could possibly inject authorization for an app before it ever ran, thus never displaying the alert box even on the apps first run in the simulator.

So how do I find what files the locationd process is opening and reading and writing to? Well, that’s where the syscall DTrace provider comes in, which allows you to probe all system calls (like open, read, write, chdir, etc.). This provider makes it really easy to find out which files a process is opening and writing to by probing the open and write functions. For example, here is a DTrace script for printing out all the files opened by the locationd process:

locationopens.d
1
2
3
4
5
syscall::open*:entry
/execname == "locationd"/
{
   printf("locationd open %s\n", copyinstr(arg0));
}

This script will trace all system calls to open* (* is a wildcard), but only on processes with the name “locationd” (the /execname == "locationd"/ line defines a predicate for the probe). The code between the curly-braces is the action to perform on each match. Inside the curly-braces we are printing the first argument to open, which is the path of the file (to find out which arguments a system call takes, use man 2 syscall which in this case would be man 2 open). We have to use copyinstr to copy data from the process into the kernel’s address space (where DTrace runs).

Running this with dtrace -s locationopens.d (make sure you have root priviledges: run sudo -i to start a new shell in root) and then running our TestingCurrentLocation app in the simulator results in a couple hundred lines that look like this:

1
2
3
4
5
6
7
8
9
10
11
12

  0    927              open_nocancel:entry locationd open /System/Library/CoreServices/SystemVersion.bundle

  0    141                       open:entry locationd open /Users/eric/Library/Application Support/iPhone Simulator/6.0/Library/Preferences/.GlobalPreferences.plist

  0    927              open_nocancel:entry locationd open /System/Library/CoreServices/SystemVersion.bundle/English.lproj

  0    927              open_nocancel:entry locationd open /System/Library/CoreServices/SystemVersion.bundle/Base.lproj

  0    141                       open:entry locationd open /System/Library/CoreServices/SystemVersion.bundle/English.lproj/SystemVersion.strings

  0    141                       open:entry locationd open /System/Library/CoreServices/SystemVersion.bundle/English.lproj/SystemVersion.stringsdict

We can get rid of some of the noise by running dtrace with the -q option, like so:

1
2
3
4
5
6
7
8
9
$ dtrace -q -s locationopens.d
...snip a bunch of lines...
locationd open /Users/eric/Library/Application Support/iPhone Simulator/6.0/Library/Preferences/com.apple.locationd.plist
locationd open /System/Library/CoreServices/ServerVersion.plist
locationd open /System/Library/CoreServices/SystemVersion.plist
locationd open /System/Library/CoreServices/SystemVersion.bundle
locationd open /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec
locationd open /Applications/Xcode.app/Contents/Developer/Platforms/iPhoneSimulator.platform/Developer/SDKs/iPhoneSimulator6.0.sdk/usr/libexec/locationd
...snip a bunch of lines...

Okay that’s a lot of file opens, and it would take awhile going through every single one looking for clues. What I really want to know is: what files does locationd write to when a user taps the “OK” button in the location alert box, and what data does it write? For that we are going to need another DTrace script:

locationwrites.d
1
2
3
4
5
syscall::write*:entry
/execname == "locationd"/
{
   printf("locationd write %s\n\n%s\n\n", fds[arg0].fi_pathname, copyinstr(arg1));
}

Here we are tracing all calls to write* and printing out the path name using the first argument (arg0) which is a file descriptor (for more on using file descriptors in DTrace, read this tutorial). We are also printing out the second argument (arg1) which is a buffer of the contents written to the file. Now if we run the script just before we confirm we want to allow this app to use our current location, we will know where locationd is writing to save this information.

This results in just one trace match writing to a file at ??/locationd/clients.plist. If we run the locationopens.d script again while grepping for clients.plist we can find the full path to this file:

1
2
$ dtrace -q -s locationopens.d | grep 'clients.plist'
locationd open /Users/eric/Library/Application Support/iPhone Simulator/6.0/Library/Caches/locationd/clients.plist

The solution

When I opened this file for the first time I had to find someone in the office to high-five. Here it was, the file that tells locationd, and thus apps in the simulator, whether or not the user has permitted use of location information. I could convert the clients.plist file into xml using plutil -convert xml1 clients.plist and then open it up and see what was inside:

clients.plist
1
2
3
4
5
6
7
8
9
10
11
12
13
14
15
16
17
18
19
20
21
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>com.codeschool.TestingCurrentLocation</key>
  <dict>
    <key>Authorized</key>
    <true/>
    <key>BundleId</key>
    <string>com.codeschool.TestingCurrentLocation</string>
    <key>Executable</key>
    <string>/Users/eric/Library/Application Support/iPhone Simulator/6.0/Applications/D2700670-4F2D-4A4B-A881-695E9812CB86/TestingCurrentLocation.app/TestingCurrentLocation</string>
    <key>LocationTimeStopped</key>
    <real>391883613.42615497</real>
    <key>Registered</key>
    <string>/Users/eric/Library/Application Support/iPhone Simulator/6.0/Applications/D2700670-4F2D-4A4B-A881-695E9812CB86/TestingCurrentLocation.app/TestingCurrentLocation</string>
    <key>Whitelisted</key>
    <false/>
  </dict>
</dict>
</plist>

Property List’s (.plist) are a strange format but not impossible to read. The real important bit seemed to be the Authorized key which was set to <true/>. I tried changing that to <false/> and rerunning the app in the simulator and my app no longer had access to location information and also didn’t bring up the location permission alert box. If I removed the entire <dict></dict> block representing my app, the location permission alert box would show back up the next time I ran the app in the simulator.

I now had full control over that location alert box. All I had to do was write over the clients.plist file with the xml already crafted in a way to give my app access to location information. For our upcoming MapKit course, we’re doing it inside our executor server (which is written in ruby), kind of like 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
def write_out_location_plist_hack!
  plist = %{
<?xml version="1.0" encoding="UTF-8"?>
<!DOCTYPE plist PUBLIC "-//Apple//DTD PLIST 1.0//EN" "http://www.apple.com/DTDs/PropertyList-1.0.dtd">
<plist version="1.0">
<dict>
  <key>com.codeschool.#{@project.project_name}</key>
  <dict>
    <key>Authorized</key>
    <true/>
    <key>BundleId</key>
    <string>com.codeschool.#{@project.project_name}</string>
  </dict>
</dict>
</plist>
}.strip

  clients_plist = File.join(
    File.expand_path("~"),
    "Library",
    "Application Support",
    "iPhone Simulator",
    "6.0",
    "Library",
    "Caches",
    "locationd",
    "clients.plist"
  )

  File.open(clients_plist, "w+") do |file|
    file.puts plist
  end
end

The code above runs before the app is launched in the simulator, and it works perfectly. We were able to get rid of the nasty CLLocationManager mocking and I was finally able to move on to something more productive.

But trying to solve this problem did lead me to learn a lot more about DTrace. Before, DTrace just seemed like this magical thing used by superhero programmers. Now that I’ve used it so solve a real problem, it’s not so magical anymore, and I am already starting to think of other problems I could solve using it that I wouldn’t have been able to before. I hope that by writing about how I used DTrace to solve this problem, it will lead you to try it out the next time you are stuck on something similar. If you do, please let me know how you did by getting in touch with me on my twitter.

The Case of the WWDC Sellout

It starts in the throat. Like a burly man with a size 13 boot stepping down on your neck, the feeling that something horrible has gone wrong.

There is a bug in production.

Any programmer that has a modicum of experience shipping software knows this feeling, because programmers are the leading cause of bugs on Earth1. It’s a terrible feeling and almost always leads to the worst day in a programmer’s life up until that point2.

But very few of us have experienced a day quite like the day one or more programmers had when WWDC “Sold Out” a couple weeks ago. The sale should have been a complete success: unprecedented demand, a rabid group of developers with their credit cards in hand. After only 71 seconds went by, the WWDC ticket site featured a prominent “Sold Out” banner and the dreams of thousands of developers were instantly crushed, yours truly included.

But then, just a few hours later, something strange happened: developers started getting mysterious phone calls from Apple letting them know they had tickets for them. I was one of the those developers. I was there as the clock rendered3 10am PST and I was able to put a WWDC ticket in my Shopping Cart4, but when I submitted the payment form I was greated with a 500 error and when I went back to the cart it was empty, and the tickets were sold out. The Apple Developer support person who called me only said that they knew that I had tried to purchase a ticket for WWDC and they still had it available for me to purchase, and that I’d be getting an email in the next 12 hours allowing me to grab it.

There have been theories as to what happened, and Marco Arment just posted his theory this weekend:

My best guess: some part of the infrastructure handling the purchases mistook 4,500 connections, transactions, or sessions for 4,500 sales. And when the front-end servers collapsed under the load of everyone hitting them at once — a first this year, since the availability time was preannounced — we all started refreshing, those connections started stacking up, and something on the back-end triggered the “Sold Out” state early because it was mistakenly counting all of those failed sessions

I think he’s close but a little bit off. My guess is that there were multiple problems with their ticket reservation system. Reservation systems are very easy to screw up5, especially in distributed systems.

Here is how I think it went down:

All the tickets were reserved (by placing a ticket into the cart you’d effectively “reserve” the ticket), and a majority of those reservations were fulfilled by the developer checking out and paying for the ticket. The rest of the reservations were wrongly fulfilled when there was a bug in the checkout process that caused an exception somewhere in the distributed stack. The checkout process failed in a way that isolated itself from the reservation system, so the final state was a fulfilled reservation, an empty cart, and an unpurchased ticket. What likely remained as evidence to the correct state of the system were log files scattered over dozens of servers and in a variety of formats. That’s why it took so long to begin calling (according to anecdotal twitter reports and my own call, I’m guessing it took 5+ hours), and why Apple couldn’t make an immediate announcement as to what happened: they didn’t know themselves.

I don’t envy the programmers who probably spent a couple sleepless nights figuring the mess out, and I am grateful that they’ve been reaching out to developers to try and get them the tickets they deserve for WWDC. As a first-time attendant, I’m looking forward to meeting an Apple engineer or two, and maybe buying them a beer or a cranberry juice, giving them a pat on the back, and letting them know that we’ve been there, we knew how they were feeling, that something terrible happened but it’s not the end of the world.

There was a bug in production.6


  1. Unproven hypothesis: I’ve created more bugs than 99% of the population

  2. Programmers are very dramatic

  3. Clocks don’t “strike” anymore, do they?

  4. We’re going to need to rethink that metaphor soon. The Amazon Generation won’t know what the hell we’re talking about

  5. I know this because I’ve written one and I screwed it up multiple times

  6. One can hope for WWDC 2013, amirite?

Announcing Try Objective-C

Badge

Today we are releasing the free Try Objective-C course to our Kickstarter backers and anyone else who wants to learn Objective-C, the language that powers iOS and Mac OS X apps.

When I first launched this Kickstarter project, I wasn’t sure what kind of response we would get. But after the first couple of days, it was clear that there were many, many people who wanted to learn how to build iOS apps. We were quickly met with a ton of requests for content for absolute beginners, people who had never coded before in their life but who desperately wanted to learn how to make iOS apps. I started work on an Objective-C Primer to give beginners a chance at learning the language before starting on iOS.

But Objective-C is a pretty complex beast of a language. And so we made it a “stretch” goal of the project to produce a full blown, free, Objective-C course.

I didn’t know what I’d gotten us into.

Being experienced programmers, sometimes it’s easy losing sight of how hard this stuff can be. We make too many assumptions and end up alienating a bunch of determined learners who feel like they aren’t being told the whole story. The problem is, the story is HUGE. Especially for a language like Objective-C. It’s an old language with a lot of power, but with that power comes a high level of complexity. Luckily, recent advances of the language (like auto-synthesized properties, object literals, and most of all ARC) have brought that complexity down to a level where it has become much easier to learn.

The rise of the popularity and use of the App Store has resulted in an interested phenomena: tons of people are entering programming for the first time by trying to learn an incredibly hard language and framework. We were reminded of this when we ran a private beta 4 weeks ago in our offices to help us with some feedback on the course and the content. We do private betas for all of our courses, and the beta for Try Objective-C had by far the most beginners of any beta we’ve had.

And unfortunately at that point our content was failing the true beginner. So we started over. We rewrote the entire course. The course we are releasing today gives the true beginner a really good shot at actually learning this language. It’s not perfect, and it’s definitely not easy, but it’s the most approachable course we could have written. And even though someone with experience in programming will most definitely start down the path of learning Objective-C and iOS with this course, it was written with someone else in mind. It was written for my brother the T-shirt printer, for my fiancée the scientist, for my friend who is a single mom, for my neighbor with all the crazy app ideas, for my dentist, for my friends, and for all the people who messaged me on Kickstarter, wanting desperately to learn a new skill, to make something meaningful, to feel like they too could become a programmer.

Setting Up KIF Integration Tests for iOS

Square released a pretty neat Integration Testing library called KIF last year and we have been using it to test the challenges for our upcoming Try iOS course on Code School. The instructions in the KIF README on setting up an Xcode 4 project are missing a couple of crucial steps, and after much Googling and Stackoverflowing I finally figured out how to get it to work, so I figured I’d share the process we are using for setting up KIF projects.

I’m assuming you already have an Xcode 4 (version 4.5.1) project that you want to add KIF to. First, if you aren’t already working with an Xcode workspace, you will need to create one for this project. To do so, choose the “Save as Workspace” menu item:

image

You need a workspace so you can manage both your original project (in my example InstagramClone), and the KIF project we are about to add the the workspace. For more on workspaces check out this Apple doc.

Next, you’ll want to download the KIF project from their downloads page, and copy the files inside of a “Frameworks” directory under the Project Root.

image

Next, go back to Xcode and command-click on empty area in the Project Navigator (⌘1), and choose “Add Files to Project”:

image

Navigate and select the “KIF.xcodeproj” file under Project Root->Frameworks->KIF. Now the Project Navigator should look like you have two projects on equal footing:

image

This is important, at this point it should not look like the “KIF” project is under the “InstagramClone” project.

Next, select your project in the Project Navigator and you should see information about Projects and Targetings in the main content area. Command-click on your app target and choose “Duplicate”:

image

Then choose “Duplicate Only”:

image

You should see a new target named “PROJECTNAME Copy”. Select the target, press Enter, and change the name to something like “Integration Tests”:

image

With the “Integration Tests” target selected, go to the “Build Phases” panel, expand the “Link Binary With Libraries” section, and click the little “+” button. Select the “libKif.a” binary from the list and add it:

image

Still with the “Integration Tests” target selected, go to the “Build Settings” panel. Make sure you have “All” and “Combined” selected:

image

Search for the “Header Search Paths” and edit the setting to add $(inherited) and $(SRCROOT)/Frameworks/KIF, like so:

image

Search for the “Other Linker Flags” setting and edit to add these flags:

image

Next, add the RUN_KIF_TESTS=1 Preprocessor Macro to both the “Release” and “Debug” targets, like so:

image

Now that we’ve configured the “Integration Tests” target correctly, we need to make sure that before Xcode builds the target, it also builds the KIF project. To do this we need to do a couple of things (this is what you won’t find in the instructions provided by Square).

First, we need to edit the “PROJECTNAME Copy” Xcode Scheme to tell it to build KIF. To do that, go to “Edit Schemes” and select the “PROJECTNAME Copy” scheme. Choose the “Build” phase. You should see something like this:

image

Click on the little “+” button right above the “Manage Schemes” button, and Add the “KIF” target:

image

Close the “Edit Schemes” dialog and go back to the Project Navigator. Click and Drag the “KIF” project to under your App project. In the dialog that appears, select both your app target and the “Integration” Tests target in the “Add to targets” section:

image

After clicking “Finish” your Project Navigator should look like this:

image.

Now you should be able to follow the rest of Square’s instructions for adding the Controller, Scenario, and Step files to test your app in the “Example” section of their README