Category: iOS Simulator

Spoofing Location Services in Your iOS Apps

Of all the instruments available on the iPhone, GPS is easily one of the most utilized. Having access to Location Services can greatly enhance user experience in your app by adapting behavior to what best suites your user based on his or her whereabouts. One critical piece to utilizing location services is making sure your code behaves the way you expect. Fortunately, in recent releases of Xcode, Apple has made this job a little bit easier by allowing us to spoof our location in the Simulator and on devices.

The way you decide to utilize Xcode’s location spoofing will depend on how your app will use it. For example, if you’re making a gorgeous weather app for the iPad, you’ll want to spoof a static location to simulate getting a user’s local weather. On the other hand, if your app does something like map a user’s bike ride, you’ll need to spoof a set of locations that simulate a user’s location changing over time. Xcode has some presets you can use for both scenarios, but more than likely you’ll want to construct your own custom data to feed to Xcode.

First, you will create a GPX file. GPX is a standard file format used for expressing GPS locations. The format for GPX files that Xcode looks for is fairly straightforward:

<gpx>
    <wpt lat="38.897678" lon="-77.036517"></wpt>
</gpx>
This GPX file gives the latitude and longitude for The White House. Throw that text into a text editor, and save it as WhiteHouse.gpx. In Xcode, open a project you have for an iPhone or iPad app, and build it to your device. Once the app is running on your device, go to Product > Debug > Simulate Location, and select the last option in the list that says “Add GPX File to Project…“, then select the WhiteHouse.gpx file we just created. Xcode will pop up some options for adding the file; the defaults should be fine, so just click on Finish. Now, if you go back to Product > Debug > Simulate Location, you should see WhiteHouse near the top of the list; click on it (you can also get to this list from the debug bar at the bottom of Xcode, just click on the location services arrow icon). Your device should now think you’re at the White House. To check, press the home button on your device to close your app and go to Maps app. If it didn’t seem to work, check Xcode and make sure the location arrow in the debug bar is blue. If it’s still gray, Xcode doesn’t like something about your GPX file.

One thing you might be wondering now is if Maps uses your simulated location, will other apps use it also? The answer is yes. Think about all the apps you have and what they are using location services for. Twitter clients posting your location with tweets, sports apps using your location to black out games, camera apps that put your location into Exif data, apps like Foursquare that check you into places – they will all look at your simulated location. I won’t go into detail here, but you should play around with this; it can be interesting.

Visiting the White House was fun, but what if you are making an app for people to track their sweet rollerblade workouts? You will need to make a GPX file with multiple location points. The format is the same but with more wpt elements that have additional latitude and longitude coordinates. I found a GPX file for the New York City Marathon here but had to make some modifications for Xcode to like it. Grab the modified file here. Click on the location button in the debug bar of Xcode, and select “Add GPX File to Project…” again. Point it to your New York City Marathon file, and accept the defaults as before. Finally, click the location button again, and select New York City Marathon from the list. Now, if you go back into Maps, you should see your blue dot making its way through the New York City Marathon; every rollerblader’s life ambition.

We’ve had quite a day so far. Any developer or tester would be exhausted after visiting The White House and rollerblading the New York City Marathon, so I won’t keep you much longer; just one more thing to show. With your app still running in Xcode, unplug your device (I will not be held responsible for any bootstrap errors that result). If you go back into Maps, you’ll find your rollerblader is stuck hanging out in New York. If you don’t stop your app in Xcode before unplugging your device, your device will continue to use the simulated location until you restart it, or until you plug it back in and turn off the location simulation. This is extremely handy for testing without being tethered to your computer. However, this can also be confusing for your mom when she sees your Facebook post from Antarctica, so don’t forget to turn it off when you have finished playing.

Hopefully, Apple will eventually give us the ability to control how quickly Xcode advances through the file. Maybe if we’re really lucky, they’ll give us a way to easily generate GPX files, or let us just specify a location without the need to create a GPX file. In the meantime, Location Simulation, while requiring a little bit of hands on work, is an extremely handy tool for testing location services in your app.

Update: For some additional information on this topic check out this article from Brandon Alexander, an iOS developer at Black Pixel. He has links for some handy tools and also covers an alternate way to enable location simulation using schemes.

Testing with the Extended Status Bar

iOS Simulator comes with a number of debug options to assist you in testing your iPhone and iPad apps. Two of of my favorite and most used options are found near the bottom of iOS Simulator’s Hardware menu: Simulate Memory Warning and Toggle In-Call Status Bar. We haven’t yet covered the in-call status bar and it’s often and overlooked and under-tested scenario that deserves some attention.

Toggle In-Call Status Bar simply enables the double-height status bar that users would normally see when they are on a call outside of the phone app. The extended status bar also appears with other background processes like tethering, voice recordings, Garage Band recordings, and Skype calls, among others. Because of the increasing number of apps that will cause this extended status bar to appear, it’s becoming more and more likely that your users will be using your app in such a scenario, and therefore increasingly important that you test for such scenarios.

There are a few different scenarios for testing the extended status bar in each view: turning on the extended status bar while you’re in a view, turning it on prior to going into a view, disabling it while you’re in a view, and disabling it while you’re out of a view. Just because a view handles one of these properly doesn’t mean it will look good in all of these scenarios. Getting familiar with the ⌘-T shortcut to enable and disable the extended status bar will help this testing go pretty quickly.

For most apps the main thing to look for when enabling the extended status bar is checking to make sure you can still scroll to the bottom of the view and nothing is being cut off. Another bug that commonly manifests is having a blank area at the top or bottom of the view that shows up when turning off the extended status bar. While many users may never even encounter these scenarios while using your app, those who do will appreciate your attention to detail if you handle these scenarios properly. Even if they don’t notice, at least they won’t be leaving you a one star review for bugs like having the back button half covered by the status bar.

Testing Memory Warnings in iOS Applications

A common cause of problems in iOS applications can be memory warnings. In the simplest terms, when the device is running low on available memory, iOS issues a memory warning which tells all running applications to stop being so greedy and to free up any memory they don’t absolutely need (and if that doesn’t free up enough, it will just start ruthlessly slaughtering them one by one). If an application doesn’t handle this properly and does something like release an object from memory without unlinking it, you can get a crash. Often times this will arise when a user has drilled down several views deep, a memory warning occurs, and as the user navigates back up the stack… kaboom! Let’s say a user is in an application, which has a photo albums view, and from there the user selects an album, and in that album they select a photo. So we have something like: Photo Albums view > Album view > Photo view.
Normally when you’d come back to something like the Photo Albums view, it would have a reference stored of which photo album you tapped on so that it could do a fancy deselect animation when you came back up out of your album view. So let’s say you’re on Photo Details, a memory warning gets issued and in an attempt to free up memory, the application releases the contents of the Photo Albums view, including the cell that you tapped and which it is holding a reference to. As you come back out of the stack to the Photo Albums view, the application will try to reference the cell for the album that you tapped, and be like “WTF? That cell doesn’t exist.” Naturally the application will throw a temper tantrum at this point, or in more technical terms, it will crash. This is just one type of scenario that can cause a crash from a memory warning. (I might cover more later, but for now it’s just important to know that nested views are where to look for these issues). Memory warnings, like all relationships, occur naturally in the wild all the time, but it’s so much easier if you can just force them to happen when it’s convenient for you. Fortunately for us, iOS Simulator provides this functionality. You can simulate a memory warning by going to the Hardware menu in iOS Simulator and selecting Simulate Memory Warning (who knows why they named it something so cryptic). You should go ahead and set a keyboard shortcut for this now because you’ll be using it a lot from now on. For this just go to System Preferences, then select the Keyboard preference pane. Then select the Keyboard Shortcuts tab, select Application Shortcuts in the left pane, then click + at the bottom. Set Application to iOS Simulator, Menu Title to Simulator Memory Warning and your shortcut to whatever you want (I went with ⌘-1 because I think memory warnings are A #1). Also remember as you’re finding these crashes to note the path you took through the views to make it happen; no need to give developers another reason to curse your name.

So now you can open up some bugs for your developers with all the crashes you’ve found. Sadly, your developers will get these crashes fixed and resolve your tickets just as you’re getting the hang of cruising around the app jamming on ⌘-1. You’ve spent your penny on the mechanical horse ride, but now it has stopped and Mom’s telling you to get off. Fear not! Crashes are only the most obvious bug to spot with memory warnings. So… what else can we look at?

Using apps should be an immersive, consistent, fluid experience for your users. One consistency that a user expects in an application is that however they leave a view, when they come back, it will be the same. For example, if you’re using the music app and you scroll down the artist list to V and tap on Vanilla Ice, when you come back to the list of artists, you expect the view to still be down in the Vs. If every time a memory warning happened while you were listening to music it meant that the Artists scroll view got reset to the top, that’s a frustrating experience. It’s important to note the different properties of your views and make sure that they are being preserved accordingly after memory warnings.

A couple of other things that are sometimes lost are the currently selected tab if you get a memory warning while a modal view is up as well as tapped cells being deselected when you come back to the view. Sometimes your developers have made sure the app won’t crash, but overlook proper behavior like deselecting a cell. Many users may not notice these details on a conscious level, but this kind of polish is what can make the difference between a good app and a great app.

Sometimes you’ll find yourself needing to test particular views on a device that don’t show up in the simulator. The easiest and quickest option for this is to launch some other applications that will eat up memory. So first plug your device in, then open Xcode and from the Window menu select Organizer. You should see your device over in the left pane with a Console option below it, select that. This is where you can get a behind-the-scenes peek at what’s going on with your device and where we’ll see when a memory warning occurs. Now that you know where to look to see when a memory warning happens, let’s figure out how to make one happen without our simulator.

One way to eat up some memory is to start a recording with Voice Memos. This option has the added luxury of allowing you to run your app in the foreground while the recording is still going and eating up memory. (It can also help you test to make sure your app resizes views properly, but we’ll go into that another time). Safari and Camera are two more apps that act like they’re trying to win Hungry Hungry Hippos when it comes to memory. In fact, for a while (I think on  iOS 5.0 or 5.0.1), if you had Voice Memos recording and tried to take a photo, both apps would crash from using too much memory. What you’ll be looking for in the console output is something like this: unknown Camera[13081] <Warning>: Received memory warning.

When you see your app receive a memory warning like this, you can then go back to your app and make sure everything still looks okay. One downfall to this method is depending on how low your device is on memory, you might find that your app has freed up more memory than you wanted it to. Instead of being taken back to the view you were expecting, you might be greeted by a splash screen indicating your application got completely killed as a result of the memory warnings (playing Infinity Blade tends to have this result). So this might take a little playing around to find the right combination of apps for you.

One final option, if your developers really love you, might be to have them put code in your debug builds that gives you buttons right in the app to generate memory warnings. This is extremely helpful for testing memory warnings on devices, but might not be an option for everybody. If it’s not an option, you might try searching around for somebody who has already written some memory warning code and made it freely available, like this guy. (Note: I haven’t tried this code, just came across it. Let me know if you have luck with it.)

As you can see, memory warning problems can manifest in a number of different ways. Hopefully with the info above, you’ll be catching these before your users do.

(Thanks to Chris Weathers for help with the explanation of memory warnings.)