Thursday, August 26, 2010

Raster Map Overlays for iPhone

The release of iOS 4.0 included the ability to add custom image overlays to maps. I recently took advantage of this in FastTrac. Previously, FastTrac was using OpenGL to handle the map. This worked well but required an unreasonable amount of memory. It also wasn’t easy to maintain. Changing to a map overlay fixed both problems. Session 127 of WWDC10 covered briefly how to implement such a map. Some sample code is also available to all developers that makes the process much easier. This session gives a good overview, but is missing some of the fine details. It is my intent to fill in the gaps. I will start with my own overview.

  1. Download and install GDAL (available at gdal.org)
  2. Download the TileMap sample project.
  3. Get the coordinates of your image’s bounding rect.
  4. Generate a .vrt file.
  5. Generate the mercator projected map tiles.
  6. Add the tiles to the sample project.
First, download and install Geospatial Data Abstraction Library (GDAL). This can be found at gdal.org. It can also be installed with MacPorts by using “sudo port install gdal”. Make sure you set your PATH variable properly. I won’t go into any details of how to do this. This shouldn’t be hard.

Next, download the TileMap sample project. This is available to all iOS developers through the WWDC10 website http://developer.apple.com/videos/wwdc/2010/. The sample code can be hard to find. It’s on the iTunes page where you download WWDC10 session videos. Between GDAL and this sample project, you as a developer won’t need to do much to get your map working.

This is where things get interesting. You will need to find the coordinates of the bounding rect of your image to overlay. Google Earth makes this easy. I got this tip from a fellow developer on the Apple developer forums. First, find the area you want to place the image overlay. Next, right click on ‘My Places’ (it’s on the left column). Select Add > Image Overlay. This will open a pop up window. From here you can open your image, change the opacity, and move/resize your image. Make your image transparent enough to see both your image and the underlying map. Once you have adjusted your image to match, click on the ‘Location’ tab. There you will find your latitudes/longitudes. You will need to convert those to a decimal value. A quick Google search will turn up a tool to make that conversion for you.

Now to put GDAL to work. The first part is to generate a .vrt (virtual raster) file. This is probably the hardest part of the process. It’s very easy to make a mistake. You will use gdal_translate to map your corner pixels to the coordinates you just found. The terminal command is as follows:

gdal_translate -of VRT -a_srs EPSG:4326 \
-gcp x1 y1 long1 lat1 \
-gcp x2 y2 long2 lat2 \
-gcp x3 y3 long3 lat3 \
-gcp x4 y4 long4 lat4 \
image.jpg image.vrt

There are a few things to note. First, your map image doesn’t have to be .jpg. Several formats are supported. Also, be very careful with your coordinates. Small errors make big problems. Notice that longitude comes first. I had them backwards and spent two days trying to figure out why it wouldn’t work. As for the x and y values, these are your pixel coordinates. (0,0) is the top left of the image.

If you have done everything correctly, the rest is easy. gdal2tiles.py will take your .vrt file and image overlay and generate mercator projected map tiles. The command is simple - “gdal2tiles.py -p mercator image.vrt.” You only need to give it the .vrt file. The .vrt file keeps a relative path to the image overlay. gdal2tiles.py will generate your map tiles along with other various files. If you don’t want these extra files there are command line options to skip them.

With your new map tiles, you simply need to add them to the TileMap project. First, delete the old tiles in the sample. Make sure they are deleted both in XCode and the source directory. If you have previously run the app, you may need to delete the app from your device/simulator. Next, copy your map tiles into your project. When copying your files, there is a vital gotcha to watch out for. You will need to create folder references instead of groups (see image below). Folder references will appear as a blue folder icon, whereas groups appear as a yellow folder icon. The reason for this is because the code is dependent on not just the files but also the directory structure.



If you named your map tiles directory any other than “Tiles,” you will need to change the code to use your directory instead. Finally, run the app and everything should work. If there is a problem, it likely occurred while generating your .vrt file.

Friday, August 13, 2010

Using a UITextField in a UIAlertView

In an app I have been working on, FastTrac WT, there is a UIAlertView with a UITextField added as a subview. Anytime the alert view was dismissed, the error “wait_fences: failed to receive reply:” would show up. It doesn’t make much sense without knowing what the problem is. That seems to be the irony of error messages. The problem turns out to be that the text field must resign its first responder status before it is released. Knowing this the error message makes more sense. The system couldn’t get a reply from the first responder. The solution to this is to resign the first responder status in the alertView:didDismissWithButtonIndex: method. Using it here makes a smooth animation. The alert view will be dismissed followed by the keyboard. An alternative is to resign the first responder status in alertView:willDismissWithButtonIndex:. The alert view and the keyboard will be dismissed at the same time and the alert view will fade and move downwards with the keyboard. This animation also looks nice and the transition is faster. However, resigning the first responder status in alertView:didDismissWithButtonIndex: does not create a smooth animation. The keyboard is dismissed before the alert view. This creates a sudden jump as the alert view re-centers itself to the viewable area. Either of the first two methods are good candidates for fixing this error. Try both and judge which animation fits best with your app.

Saturday, August 7, 2010

My First Quartz Composition

Quartz composer is often used for making screensavers. So, to learn QC, I decided to make a screensaver of my own. I started with a simple concept, two spheres orbiting around each other. I thought it would be simple anyway. All of the motion is accomplished through the use of LFOs (low-frequency oscillators). At first, I thought I could use three LFOs, one for each axis, to generate the desired motion. I couldn’t find anyway to get this to work. In the end, I found an alternative solution. Each sphere has two LFOs that cause the sphere to orbit in the yz-plane. From there, I used a 3D transformation patch to rotate the two spheres about the y and z axes. This achieved the movement I mentally envisioned. Much of my efforts were trial and error. There is very little documentation available for QC. I hope this to change in time.

Below is a link to my Quartz Composition for anyone interested.

http://dl.dropbox.com/u/2998162/Quartz%20Composer/Orbiting_Spheres.qtz

My First Quartz Composer Patches

While playing around with some of the standard Quartz Composer patches, I discovered the Apple remote patch. I just so happen to have an Apple remote, so I wanted to give it a try. I found it to work well. However, the remote only emitted a quick “true” signal. For what I wanted to do, I needed to store a boolean state. A previous electrical engineering course helped me come up with the solution. I built an RS flip flop patch. An RS flip flop is a simple electrical circuit that stores a single state. It consists of only two NOR gates that are cross-coupled. By setting one wire high (true) the stored bit will go high. When the other wire is set high, the stored bit will go low (false). While both wires are low, the bit will remain unchanged. However, both wires shouldn’t ever both be set high. The result is undefined.

This new patch suited me well. The only problem was that it required using two buttons and those buttons couldn’t be pressed simultaneously. I, of course, could do better. I added a few more components to my patch and changed it to a toggle switch. This permitted one button to toggle between the two states. I later discovered that there is a standard toggle patch, but it can toggle between any two numbers. Mine specifically uses boolean values.

Below are links to download the two patches I developed for those who are interested. Note that since these are patches, not macros, the underlying logic is not available to view.

http://dl.dropbox.com/u/2998162/Quartz%20Composer/RS_Flip_Flop.qtz
http://dl.dropbox.com/u/2998162/Quartz%20Composer/Toggle_Switch.qtz

Tuesday, July 6, 2010

C++ Templates

Today I was working on some standard C++ data structures for a CS class. I wanted to make them generic so that they could be used to hold any primitive or object. C++ offers this flexibility with templates. I found some simple tutorials and went at it. When I was finished, I couldn’t get them to work. I kept getting an undefined reference error during the linking process. What made it the most challenging is that everything was syntactically correct. I had to scour the internet to find the answer. It turns out that with C++ templates, the implementation must be included in the header file. There are a few ways to accomplish this. First, is to use the “export” keyword just before declaring the template. This option isn’t supported by most compilers. I have been using g++ which does not support this feature. Second, the .cpp file can be #included at the end of the .h file. I didn’t prefer that approach. Third, the implementation can be copied to the end of the header file. This is essentially the same as the second option. The fourth option is to simply define each method as soon as it is declared. Any of these four options will essentially merge the implementation and header files directly or indirectly. I took the last option. Once my files were merged, my data structures worked perfectly. Again, it is always the fine details that create the biggest problems.

Thursday, June 3, 2010

Action Sheet Won't Cancel

Here’s another little problem that has perplexed me for some time. I noticed that when using a UIActionSheet, sometimes the cancel button appears to be unresponsive. Typically it must be tapped several times before dismissing the action sheet. I finally decided to take a look around stackoverflow to see if anyone else has noticed such behavior. I found exactly the answer I was looking for. The problem is that I was using a UITableView in a UITabBarController. When I was displaying the action sheet, I was showing it from the table view. By doing this, only the top most part of the cancel button works. This is because the hit testing won’t work properly. The system will think that we are tapping on the tab bar rather than the action sheet. This is fixed by changing one line of code. Rather than use the usual
[actionSheet showInView:self.view];
instead use
[actionSheet showInView:self.parentViewController.tabBarController.view];
This will show the action sheet from the tab bar controller and hit testing will work as expected.

Saturday, May 15, 2010

Twitter Integration

I previously wrote about Facebook Connect. However, Facebook is not the only social network out there. Twitter is another popular network.

The implementation process is similar to Facebook Connect. I will list the steps:
  1. Register your app with Twitter.
  2. Download and copy MGTwitterEngine into your source code.
  3. Create an MGTwitterEngineDelegate and an MGTwitterEngine object.
  4. Create your own login page for Twitter.
  5. Pass the user’s credentials to MGTwitterEngine.
  6. Authenticate the user’s credentials.
  7. Start tweeting!
To start, you will need to register your app with Twitter. This can be done at http://dev.twitter.com/. This is also where you will find all of the API documentation and other information. Unlike Facebook, only one user can be a developer for a particular app. So, you may want to create a Twitter account specific to your app or company to handle the development of your Twitter features.

Another point to note is that after June 30, 2010 your app will have to use OAuth (or xAuth) for authentication. I won’t go into the details here. Consult the Twitter documentation for details.

Now you can start implementing Twitter into your app. Unfortunately, Twitter doesn’t have a convenient Xcode project to use. This will require using some third-party software. I used MGTwitterEngine. It is produced by @mattgemmell. His code can be found at http://mattgemmell.com/.

MGTwitterEngine revolves around the use of the MGTwitterEngine object. This isn’t nearly as advanced as Facebook Connect. You will have to handle the login dialog and automatic re-login on your own. A user’s credentials can be securely stored in the iPhone’s keychain. Details on the keychain can be found in the iPhone API.

Logging in takes several steps. You will first need to create an MGTwitterEngineDelegate before creating an MGTwitterEngine object. Once you have prompted the user for their user name and password, this can be passed on to MGTwitterEngine by the following method:
[twitterEngine setUsername:(NSString *)name password:(NSString *)password];
However, this does not authenticate the user name and password. It simply stores them in the MGTwitterEngine. Verification can be received by calling:
[twitterEngine checkUserCredentials];
This will make a call to the API to verify the user’s credentials. This method does not wait for the verification to return. Instead, one of two MGTwitterEngineDelegate methods will be called when the verification returns. These two delegate methods are:
- (void) requestSucceeded:(NSString *)requestIdentifier
- (void) requestFailed:(NSString *)requestIdentifier withError:(NSError *)error

Since these calls occur asynchronously, you will need to handle this accordingly. Some options include blocks, GCD, and/or how ever else you want to handle it.

From here you are ready to start using Twitter from your app. MGTwitterEngine provides several methods for doing various actions. One you will likely use is
[twitterEngine sendUpdate:@“Hello World!”];
This will send a tweet as you would expect. Remember to keep tweets to 140 characters.

Your now ready to make Twitter a part of your apps. Happy Tweeting!

Friday, May 14, 2010

Facebook Connect

UPDATE: This post was written for the Facebook REST API. The REST API is now deprecated and you should use the Graph API instead. I may write a new post on the Graph API in the future.

This time I’m returning to a topic I learned months ago - Facebook Connect. However, I need a refresher on it. One of the great luxuries of programming is adding functionality without writing the code personally. Fortunately, Facebook has created an API that works well on a multitude of platforms. With this API, an iPhone app can become more interactive as users share with others what they are doing with it. This also results in an app receiving greater visibility to the public.

Anyway, several months ago I added Facebook and Twitter support to Police Scanner 2. My biggest struggle with implementing Facebook support was that the iPhone documentation is very minimal and not as explicit as I would like. I figured out almost everything simply by trial and error. Hopefully this blog post will shed more light on the subject.

This tutorial is lengthy, so I will start with an overview of the steps:
  1. Create a Facebook app.
  2. Download and copy Facebook Connect into your source code.
  3. Create an FBSession with your API key and secret key.
  4. Login to Facebook via a FBLoginButton or FBLoginDialog.
  5. Enable auto re-login.
  6. Create delegate(s) that conform to the FBSessionDelegate and FBRequestDelegate protocols.
  7. Request the permissions you need.
  8. Perform actions with FBRequest.
One of the first steps to take in implementing Facebook Connect is creating a Facebook app on Facebook itself. To do this, you must add the Facebook Developer app to your profile. Finding the app is near impossible. I found it through a link on the developers page. The URL to the app is http://www.facebook.com/developers/. From there a Facebook version of your app can be created. Even though you are creating an “app,” you won’t be using it as an app. Instead, this will be the channel through which your iPhone app will interact with Facebook. This also provides some basic analytic information and creates a Facebook page for your app. I won’t go into any of the details of how to set everything up. That could be a lengthy topic by itself. Personally, I found the basics to be straightforward enough. There are many advanced capabilities that can be explored if you so desire.

With your Facebook app in place, you can now start adding the functionality to your iPhone app. You will need the Facebook Connect Xcode project. You can Google it or find it here. I found it easiest to copy the Facebook Connect project code into your own project. The greatest part of Facebook Connect is that almost everything is done for you.

Once the code is copied into your project, just #import “FBConnect.h”. Next, create a FBSession object. You should retain this object for the lifetime of your application. This is where you will need your previously created Facebook app. On the application settings editor page there is an API key and app secret key. These are necessary for creating your session object. They can be stored as string constants and passed in as parameters. the following gives an example of this.
session = [[FBSession sessionForApplication:FBAPIKey secret:FBSecretKey delegate:self] retain];

Next, to login to Facebook. This can be two different ways. The easiest is to create a FBDialogButton and add it wherever you please. If my memory serves me well, there are three different sizes of buttons that can be used. Alternately, you can create a FBLoginDialog and call that however you like. This can be done as follows:
FBLoginDialog * dialog = [[[FBLoginDialog] alloc] initWithSession:session] autorelease];
[dialog show];
Either way, a nice login dialog pops up and takes care of everything.

Facebook Connect handles automatic re-login. All you need to do is call [session resume]; when your app starts. If a user has never logged in or explicitly logged out, then this will do nothing. Also, sessions automatically expire if they are left idle for two hours.

I failed to mention earlier that you will need an object that conforms to the FBSessionDelegate protocol in order to create a session. It has a single required method:
- (void)session:(FBSession *)session didLogin:(FBUID)uid;
You can use this method as an opportunity to set a flag in your app that the user has logged into Facebook. This is also a great opportunity to request any permissions you will need later.

While on the topic of permissions, I will expound some more. FBPermissionDialog is used to request different permissions. This has two delegate methods as defined in FBRequestDelegate.
- (void)dialogDidSucceed:(FBDialog *)dialog;
- (void)dialogDidCancel:(FBDialog *)dialog;
It should be clear which does what and when it is called. The following is an example of requesting permission to publish to a user’s stream:
if (!FBPermissionsGranted) {
        FBPermissionDialog * dialog = [[[FBPermissionDialog alloc] init] autorelease];
        dialog.delegate = self;
        dialog.permission = @"publish_stream";
        [dialog show];
}

There are several different permissions that can be requested. Consult the Facebook documentation for the specifics. The only change that needs to be made to the following code is the string representing the desired permission.

One important note, Facebook remembers if a permission was previously granted. So if you request the permission a second time, the dialog window pops up and immediately closes. This quick flash is annoying and should be avoided. This can be done by saving the state of permissions granted and/or making an API call that requests the user’s granted permissions.

Now that you’ve got a user to login and granted the necessary permissions, let’s have your app do something. This is done through FBRequest. A request will look something like this:
[[FBRequest requestWithDelegate:self] call:@“some action here...” params:params];
The string is the API call to use. For example, to publish to a user’s stream call @“facebook.stream.publish” or update a user’s status with @“facebook.Users.setStatus”. The params is an NSDictionary that contains the parameters specific to that API call. Consult the Facebook API for the details. Some parameters are optional whereas others are required. If we were to publish something to the user’s stream we could set up the parameter like this:
NSDictionary *params = [NSDictionary dictionaryWithObject:@“Hello World!” forKey:@"message"];

FBRequests are where the action of Facebook Connect comes in. With the proper permissions you can do anything with a FBRequest. For example, you can upload videos, check if a user is a fan of a particular page, create events, etc. Basically, anything you can do on the Facebook website, you can do from the API. Just call the desired method, such as “video.upload,” “page.isFan,” or “events.create,” then pass in the necessary parameters. Facebook even has their own query language (FQL). This is comparable to SQL. Another point to note is that Facebook also provides a test console with each API call to test if a call works and what exactly it is returning.

I hope this lengthy tutorial is beneficial. I provided only simple examples, but really your imagination is the limit. Most of the process is very implement. The challenge comes in when making requests. Getting the parameters and return values right can take some trial and error. Making use of the Facebook test console makes life much easier.

Monday, May 10, 2010

UITableViewCell Reuse Cautions

Here’s a problem that perplexed me for quite some time today. I was making an options page for an iPhone app. I set up a UITableView with a few different sections. Each section contained different kinds of options such as dates, times, and switches. Due to the variations in options, some cells were set up differently from others. For the switches, I added a UISwitch as a subview to the content view of a cell. For dates and times, I was displaying the date or time as a detailed text label. Everything looked nice, that is until I scrolled. When scrolling, the cells had a mix of UISwitches and text labels mixed together. It was a mess. After several hours of reading documentation I uncovered the source of the problem. Ironically, it was something small and simple. When a cell scrolls off the screen it is reused as one of the cells scrolling onto the screen. Normally there are no problems with cell reuse because the cells of a table are usually uniform in use and layout. When a cell is recycled, all of the old values are usually overwritten by the new values. In my case, I wasn’t using all of the properties for all of the cells. This lead to the conflicts that left me bewildered for so long.

Removing the detailed text label was easy. All I need to do was set the it to an empty string. Removing the UISwitch wasn’t as easy. Fortunately, I found a piece of code on stackoverflow.com that helped me out. What I did was get all of the subviews from the cell’s content view and release them. It looks like this:

NSArray * subviews = [[NSArray alloc] initWithArray: cell.contentView.subviews];
        
for (UIView * subview in subviews)
        [subview removeFromSuperview];
        
[subviews release];

It was a small change but made all the difference. With those changes in place, my options page was flawless. I never cease to be amazed by all the bugs that result from simple mistakes.

Saturday, May 8, 2010

Deleting cstrings

While working on a URL resolver project, I came across a curious aspect of the nature of cstrings. To start out, I was creating a URL object with a string constant as an input. Example: URL * url = new URL(“http://www.google.com/“); In my URL object, I was simply pointing to whatever string was passed in. I should have known better than to do that. Java has made some bad habits in me. Aside from that error, I noticed that I would always get a segfault when trying to delete the cstring the URL was stored in. Later I found that this error was eliminated by copying the string input rather than simply pointing to it. After looking through some memory dumps I have concluded that the reason for the segfault was due to attempting to delete memory that I didn’t have permission to access. In this case the string constant I was passing in was part of my program. I could really make a mess of things if I had been permitted to overwrite that memory.

EDIT:

Since writing this post, I have learned that string constants are stored in the static data area of the memory model. This is separate from where the code is stored in the memory model.

Saturday, May 1, 2010

Makefile Exploration

In my preparation for CS 240 this upcoming summer term, I delved into the C++ and Makefiles. For one of the class projects we will be making some basic data structures. I got a great start one them. There’s really not much to linked lists and such anyway. Not far into the project I grew tired of compiling everything by hand. Plus, one requirement of the project is to create a makefile. I had some previous experience with makefiles from CS 124. I looked up my old makefiles and had a good makefile up and going in no time.

Of course, as a good developer, I wanted to make the most out of code reuse. I wanted to create makefiles for following projects with little or no effort. A quick Google search revealed exactly what I was looking for. I found a short, simple makefile example that I could customize to my needs by changing only a couple lines.

After reading through more of the requirements for the projects, I soon discovered that the overall structure of the project was more complicated than I anticipated. All of the source files were to be in one directory, the header files in their own, the unit tests in another, and so on. My simple makefile only worked when all of the files were in the same directory. This time, not even Google could find results that worked for my particular wants.

I consulted the GNU make documentation directly. After a couple hours of thorough studying, deep thought, and many errors, I arrived at a solution. My first difficulty came with accessing the different files. I had a variables for each of the directories and a variable containing all of the source file names. The problem was combining the two so that directory didn’t have to be specified for each source file name. It turns out that make has a foreach function. That easily fixed the first problem.

Once the file access problem was resolved only one more problem stood in the way. This one stumped me for a while. My rule that compiled .cpp files to .o files didn’t seem to be working. The target name was .cpp.o: (this is shorthand for %.o: %.cpp). Even the GNU make manual didn’t supply a sufficient answer to this puzzle. The answer came while poking around stackoverflow.com. Someone else had a related question. From some sample code provided I changed my target to $(OBJ_DIR)/%.o: $(SRC_DIR)/%.cpp. OBJ_DIR is a variable containing the name of the directory to where .o files are stored and SRC_DIR is where the source files are kept. What I came to realize is that although the % operator for all intents and purposes is a wildcard, it stays within the directory. Basically, my rule was telling the makefile to look for any .o and .cpp files in the root directory of my project. What I really wanted was the makefile to look in the respective directories for the files. As always, it’s the simple mistakes that trips up a program.

In addition to creating the basic targets, I created a few others for convenience. Some include clean, test, run, etc. I haven’t done anything yet with building unit tests and library files. That will come in due time as I find out more of what my professor expects.

I would post my source code, but I won’t so that my fellow students won’t be tempted to copy and use it without first learning how everything works by themselves. However, my source code is available at request.

Intro

The purpose behind creating this blog is twofold. First, I am documenting what I learn as I dive into various topics of programming. I often find I learn something new or discover a solution to a bug just to forget and relearn it at a later time. Second, I hope that what I document may be insightful to others who are learning for the first time or have encountered similar difficulties.