Posts Tagged ‘code’

How to Retrieve Your App Delegate Singleton Instance

December 14th, 2009

You should be familiar with the application delegate class if you have ever developed any kind of iPhone app. It is the class that contains your app’s applicationDidFinishLaunching which most if not all apps use as an entry point for execution. You might use it to keep track of application-level state variables or objects, for example.

As such, from time to time you will have a need to retrieve your app’s application delegate instance. You can retrieve it from anywhere within your app by running the following single line of code:

MyAppDelegateClass *app = [[UIApplication sharedApplication] delegate];

Just be sure to replace “MyAppDelegateClass” with your own iPhone app’s application delegate class name.

How to Get Your App’s Display Name and Version

December 13th, 2009

Have you ever needed to retrieve your iPhone app’s name or version at runtime? Sure, you can use constants in a lot of cases, but it can often save you time in the long run to make use of the information that is available via a class called NSBundle.

The Code

You can retrieve your iPhone app’s display name using the following one line of code:

NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];

To retrieve your iPhone app’s version number, use the following similar line of code:

NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];

Use Case

Screen shot 2009-12-13 at 12.41.07 PMIn Addicus, when you click the “Get Set” button on the main menu, it links to our website and passes in the referring application name and app version as querystring parameters, allowing us to track visits to our website from different versions of all of our iPhone games. To do this, we combine the above code with code that opens a URL. Here is the resulting code:

NSString *appName = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleDisplayName"];
NSString *appVersion = [[NSBundle mainBundle] objectForInfoDictionaryKey:@"CFBundleVersion"];
NSString *url = [NSString stringWithFormat:@"http://getsetgames.com/?r=%@&v=%@",appName,appVersion];
 
[[UIApplication sharedApplication] openURL:[NSURL URLWithString:[url stringByAddingPercentEscapesUsingEncoding:NSUTF8StringEncoding]]];

Since we’re retrieving this info via the NSBundle class, we never need to change this code when we update the version of the app. The version change propagates down to the URL we open automatically. And this code can be reused in any app without changing it.

How to Dial a Phone Number

December 12th, 2009

photo-4With so many awesome games and apps on the iPhone, it is easy to forget that it can actually be used to make phone calls. No, really, it’s true! And as is the case with so many other pieces of functionality, this is easy to accomplish with the iPhone SDK.

Like other phones, the iPhone supports the tel application protocol in URLs. This means that all we need to use is the trusty openURL method of the UIApplication class. We have previously discussed this method when pre-composing emails and, believe it or not, opening a URL.

The Code

Here is how to dial a phone number from your iPhone app in one line of code:

[[UIApplication sharedApplication] openURL:[NSURL URLWithString:@"tel:555-555-5555"]];

Dialing From a Web Page

You can also put links in your web pages that dial a phone number on the iPhone by using the tel protocol like so:

<a href="tel:555-555-5555">Dial 555-555-5555</a>

How to Hide (and Show) the Status Bar

December 11th, 2009

On the iPhone’s 320×480 screen, pixel real estate is at a premium, especially for games. Often, the status bar represents 20 pixels of height that you as a developer just can’t afford to give away. Fortunately there are 2 simple ways to remove the status bar.

UIStatusBarHidden

uistatusbarhidden2The first way is by adding a setting to your app’s info.plist file called UIStatusBarHidden. This is ideal for apps that should never display the status bar. Just follow these steps to change the setting:

1. Open your iPhone app’s info.plist file.

2. Command-click and select Add Row.

3. Select “Status bar is initially hidden” from the drop down that appears.

4. Check the checkbox that appears next to the new row.

You could also add this setting to your app’s info.plist file by opening it in a text editor and adding the following 2 XML tags inside the <dict> tag:

<dict>
	<key>UIStatusBarHidden</key>
	<true/>
	...

How to Do it With Code

If you need the status bar to appear and disappear at runtime, then you will need to use code to do so. You can hide the status bar with one line of code:

[[UIApplication sharedApplication] setStatusBarHidden:YES animated:NO];

And to show it again, simply call the above line and pass “NO” into setStatusBarHidden instead of “YES”. You can also fade the status bar in and out by passing “YES” into the “animated” part of the message.

String Comparison Using NSString

December 10th, 2009

Photo-2a

One of the most common things a programmer needs to learn how to do when faced with a new API is how to compare one string to another to see if the two are the same or how they differ.

Because of this, many APIs have created some handy string comparison features, and the NSString class in objective-c is no exception. What follows are some invaluable tools for string comparison in objective-c.

The Is-Equal Method

The NSString class responds to a message and returns whether or not the NSString you pass in is equal or not:

NSString * str = @"oranges";
BOOL res = [str isEqualToString:@"apples"];

The Compare Method

The NSString class also has a method called compare, which gives you a bit more info in the return results. It can actually tell you the difference between the two strings; whether or not the string you passed in is:

  • the same,
  • in ascending sort order to the string you call the message on or
  • in descending sort order to the string you call the message on
NSString * str = @"oranges";
NSComparisonResult res = [str compare:@"apples"];
 
switch (res) {
	case NSOrderedAscending:
		// going up
		break;
	case NSOrderedSame:
		// even steven
		break;
	case NSOrderedDescending:
		// down i go
		break;
	default:
		break;
}

Insensitivity to Case

Finally, the NSString class also features a method for comparing strings without case sensitivity. This is useful for comparing strings with unpredictable case, such as user input. Like the compare method, it returns an NSComparisonResult enumerated value which allows you to see the equality or sort-order of the two strings.

NSString * str = @"APPLES";
NSComparisonResult res = [str caseInsensitiveCompare:@"apples"];
 
switch (res) {
	case NSOrderedAscending:
		// onward and upward
		break;
	case NSOrderedSame:
		// same old
		break;
	case NSOrderedDescending:
		// downfall
		break;
	default:
		break;
}

How to Get the Platform Name

December 8th, 2009

With each iPhone OS-powered device that Apple has added to its lineup, along with it has come new capabilities and new APIs. Because of this, it is often necessary for an app to figure out what platform it is running on before deciding to enable device-specific functionality, such as functionality that would use the compass on the iPhone 3GS, vibration on iPhones or GPS on iPhones.

Here is a function that serves just that purpose by returning the internal name of the platform:

#include <sys/types.h>
#include <sys/sysctl.h>
 
-(NSString*)getPlatformName {
	size_t size;  
	sysctlbyname("hw.machine", NULL, &size, NULL, 0);  
	char *machine = (char*)malloc(size);  
	sysctlbyname("hw.machine", machine, &size, NULL, 0);  
	NSString *platform = [NSString stringWithCString:machine encoding:NSASCIIStringEncoding];
	free(machine);
 
	return platform;
}

Possible Values

The possible values that the above function will return when developing for the iPhone OS are listed below along with the product they represent.

Return Value Product
i386 iPhone Simulator
x86_64 iPhone Simulator
iPhone1,1 iPhone 1G
iPhone1,2 iPhone 3G
iPhone2,1 iPhone 3GS
iPhone3,1 iPhone ?
iPod1,1 iPod Touch 1G
iPod2,1 iPod Touch 2G

Example Usage

The following is an example of an if statement that takes advantage of the results of the above function.

NSString * platform = [self getPlatformName];
 
if ([platform isEqualToString:@"i386"]) {
	// do simulator-specific stuff, perhaps enable a more verbose level of logging?
}
else if ([platform isEqualToString:@"iPod2,1"]) {		
	// do iPod-specific stuff, perhaps disable UI that refers to GPS, vibration, etc.
}
else if ([platform isEqualToString:@"iPhone2,1"]) {
	// do iPhone 3GS-specific stuff, perhaps compass related?
}

How to Get the Current Time with NSDate

December 7th, 2009

In iPhone app development, timing is everything. Being able to take a pulse on the current time is crucial to many apps, especially games. Fortunately, this can be done with as much ease as a developer would expect using the NSDate class in the iPhone SDK. Today’s iPhone development advent tip is another one-line wonder:

NSTimeInterval time = [[NSDate date] timeIntervalSince1970];

The timeIntervalSince1970 method returns the number of seconds since epoch. The return value type, NSTimeInterval, is a typedef of double, so you will have the necessary accuracy to get the current milliseconds from the first 3 digits after the decimal if need be.

How to Open the Mail App With a Pre-Composed HTML Email

December 6th, 2009

photo 2-1Have you ever wanted to open the Mail app with a pre-composed email? Then today’s iPhone development advent tip is the one for you! This has many uses, but a common one is a tell-a-friend feature in apps. If you attach the code from this tip to a button, you can give your users a way to promote your app to their friends via the iPhone’s built in Mail app.

A Handy Function

The sendEmailTo function, seen below, can be included in any class in your app. This function gives you a simple interface to send emails. It allows you to define “to” addresses, “cc” addresses, “bcc” addresses, a subject and a body. The body supports HTML tags.

- (void)sendEmailTo:(NSString*)to withCC:(NSString*)cc withBCC:(NSString*)bcc withSubject:(NSString*)subject withBody:(NSString*)body {
	NSString * url = [NSString stringWithFormat:@"mailto:?to=%@&cc=%@&bcc=%@&subject=%@&body=%@",
					  [to stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
					  [cc stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
					  [bcc stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
					  [subject stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding],
					  [body stringByAddingPercentEscapesUsingEncoding:NSASCIIStringEncoding]];
 
	[[UIApplication sharedApplication] openURL:[NSURL URLWithString:url]];
}

NOTE: Running this function in the iPhone Simulator will have no effect because the simulator does not include the iPhone’s Mail app. To see the effects of this function, it must be run on a device.

Example Usage

Once you have that message defined in one of your classes, you can open the Mail app with a pre-composed email with just one message call. The following example opens an email and specifies a to, cc and bcc address. It populates the subject with “Addicus” and populates the body with a short message about Addicus that includes a link and an image (which is also a link). As you can see, this is done with good old HTML tags. This results in the email in the above screenshot.

[self sendEmailTo:@"mom@example.com"
           withCC:@"dad@example.com"
          withBCC:@"asecretfriend@example.com"
      withSubject:@"Addicus"
         withBody:@"<p>Check out this game, <a href='http://addicusgame.com'>Addicus</a>, for the iPhone and iPod Touch. It's super-addictive!</p><p><a href='http://addicusgame.com'><img src='http://getsetgames.com/wp-content/uploads/2009/11/icon_addicus.png'/></a></p>"];

If you would like to have the user specify the to, cc and bcc addresses themselves, as you would in the case of a tell-a-friend button, then you would call the following message:

[self sendEmailTo:@""
           withCC:@""
          withBCC:@""
      withSubject:@"Addicus"
         withBody:@"<p>Check out this game, <a href='http://addicusgame.com'>Addicus</a>, for the iPhone and iPod Touch. It's super-addictive!</p><p><a href='http://addicusgame.com'><img src='http://getsetgames.com/wp-content/uploads/2009/11/icon_addicus.png'/></a></p>"];

How to Load a UIImage From a URL

December 5th, 2009

Early on in development of Addicus, we discovered how easy it was to load images from the web. This was a huge boon to us since it meant our artists could modify assets on our server and they would update live in the test builds, without having to make a new build.

This all hinged on the ability to load a UIImage from a URL. And as it happens, this can be accomplished in as little as one line of code:

UIImage * img = [[UIImage alloc] initWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:@"http://example.com/image.png"]]];

This eventually led to us writing a resource manager singleton class that handles all of our resource loading and can be toggled between local and web mode.

Eliminating class dependencies on your application delegate

December 4th, 2009

Ever have the need to call a method inside your app delegate from an arbitrary place in your code?  We’ve had to deal with this issue in a few cases working on our new project.  We’re making use of a UIScrollView instance to give us that popular flick scroll movement that is so popular on the iPhone.  We’ve found that alot of people have been interested in doing the same thing and you can read our blog on that particular challenge here.  We have a UIScrollView instance sitting inside our app delegate and there are certain parts of our code where we need to move that UIScrollView among different layers in Cocos 2D.  To do that we need access to the scroll view instance itself.  That results in code like the following…

myAppDelegate *app = [[UIApplication sharedApplication] delegate];
UIScrollView *appOverlayScrollView  = (UIScrollView *)app.view;
[[app window] sendSubviewToBack:appOverlayScrollView];

This creates a messy dependency between an arbitrary class and the app delegate class.  Wouldn’t it be great if we could send a message to the app delegate and tell it to move the scroll view to the front or back maintaining encapsulation?  Turns out you can indeed do this.  The UIApplication class contains a method called sendAction which is normally used to send an action message identified by a selector to a specified target.  This method can easily be used to call selectors in any object so the above code can be converted to…

[[UIApplication sharedApplication]
sendAction:@selector(bringScrollViewToFront)
to:[[UIApplication sharedApplication] delegate]
from:self
forEvent:nil];

The only downside to this approach is that I haven’t found a way to supply arguments along with the selector so you need to be calling a method with no arguments.  If you know of a way around this issue please do let me know.