— boreal-kiss.net

Archive
Tag "ipad"

One of my drawings became the cover art of Simian Mobile Disco‘s new album, Unpatterns, with which you will experience impressive Moiré patterns both on CD and vinyl. The shape of the drawing is inspired by Bridget Riley‘s Riley Waves.

There is also an associated iPhone app, where you can listen to their full album with interactive contents same as my Moiré app plus exclusive shapes. This is also a part of the collaboration.

Available on the App Store

Read More

In order to make an application universal one has to detect the device’s idiom (iPhone/iPad) at run time. This is easily done with the following conditional:

if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
	//iPad specific codes.
}
else{
	//iPhone specific codes.
}

You might have used this conditional, for example, when you want to control a view’s rotation or a modal view’s behavior depending on the current device’s idiom. The above conditional is simple and easy to implement when the application is simple. However once the application has lots of behaviors varying on the device’s idiom here and there, your source codes will get messy and hard to read and/or maintain, due to the duplication of this snippet spreading over your project.

Fortunately this will be easily resolved by using the well known State pattern. As the name suggests, State pattern deals with the internal state of its participating context and does some work without unnecessarily exposing other states that the context could have. As describing such patterns only in words is always hard to figure out, I’ll give you an example to walk through with.

Example

Consider the following situation. You want to control a view’s rotation depending on the device’s idiom:

  • On iPhone, the application allows one of portrait modes (Home button at the bottom).
  • On iPad, the application allows both portrait and landscape modes.

The implementation for this in a straightforward way looks like this:

-(BOOL)shouldAutorotateToInterfaceOrientation:
					(UIInterfaceOrientation)interfaceOrientation{
 
	if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
		//iPad.
		return YES;
	}
	else{
		//iPhone.
		if (orientation == UIInterfaceOrientationPortrait){
			return YES;
		}
		return NO;
	}
}

In this example, I’ll add some tweaks for the above snippet to look cleaner. That is:

  1. Wrap the codes inside the conditional into a block object.
  2. Register them in a dictionary object.
  3. Retrieve the block object from the dictionary when needed.
  4. Invoke the block.

1-2. Create blocks and register them in dictionaries

The key trick here is wrapping into blocks will done for iPhone and iPad separately:

//For iPhone.
BOOL (^blockiPhone)(UIInterfaceOrientation orientation) = 
						^(UIInterfaceOrientation orientation){
	if (orientation == UIInterfaceOrientationPortrait){
		return YES;
	}
	return NO;
};
 
[_dictionaryForiPhone setObject:[[blockiPhone copy] autorelease] 
						forKey:@"viewRotation"];
//For iPad.
BOOL (^blockiPad)(UIInterfaceOrientation orientation) = 
						^(UIInterfaceOrientation orientation){
	return YES;
};
 
[_dictionaryForiPad setObject:[[blockiPad copy] autorelease] 
						forKey:"viewRotation"];

Here the dictionary objects as a registry assume to be instance variables in the class.

NSMutableDictionary *_dictionaryForiPhone;
NSMutableDictionary *_dictionaryForiPad;

Note that although the value of the key string here is arbitrary, you would better give a meaningful name for its later usage. Also note that since block objects are yet in the stack, they must be copied to the heap before adding to the collections.

3. Retrieve blocks

Then I provide a method retrieving a appropriate block object corresponding to the device’s idiom:

//Incomplete.
-(id)blockForKey:(NSString *)key{
	if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
		return [_dictionaryForiPad objectForKey:key];
	}
	else{
		return [_dictionaryForiPhone objectForKey:key];
	}
}

This is redundant since the conditional inside the method gets evaluated each time the method gets called. So add I additional tweaks. These look like this;

//Complete
-(id)blockForKey:(NSString *)key{
	if (!_idiomDetected){
		if (UI_USER_INTERFACE_IDIOM() == UIUserInterfaceIdiomPad){
			_dictionaryForCurrentIdiom = _dictionaryForiPad;
		}
		else{
			_dictionaryForCurrentIdiom = _dictionaryForiPhone;
		}
		_idiomDetected = YES;
	}
 
	return [_dictionaryForCurrentIdiom objectForKey:key];
}

Here two new instance variables are introduced:

BOOL _idiomDetected;
NSDictionary *_dictionaryForCurrentIdiom;

The boolean value is used for testing whether the application already detected the device’s idiom or not. If detected the application skips the conditional. If not, the application tries to detect the current device’s idiom and assign the reference to the appropriate block dictionary to _dictionaryForCurrentIdiom. Doing this, block objects will be retrieved only from this referencing dictionary, hiding the fact that there are actually two different collections of blocks (iPhone/iPad), thanks to State pattern.

4. Invoke blocks

Finally the above method will get called in the right place:

-(BOOL)shouldAutorotateToInterfaceOrientation:
					(UIInterfaceOrientation)interfaceOrientation{
	BOOL (^block)(UIInterfaceOrientation) = [self blockForKey:@"viewRotation"];
	return block(interfaceOrientation);
}

Note that in order to invoke a block correctly one must know the type of the block properly (Since you are the adder of blocks, you must know well their types, right?).

Now my codes are free from conditional, looking very tidy. Although the example here is trivial, this pattern will give you its real strength when the application has more and more device specific behavior (controlling modal views, if iPhone 4S, if iPad 2, and so on).

BKUIIdiomController

If you want to try this but save your time, here is my idiom controller class. The class only has two APIs:

-(void)setBlockForiPhone:(id)blockForiPhone 
				blockForiPad:(id)blockForiPad forKey:(NSString *)key;
-(id)blockForKey:(NSString *)key;

The first method for registering blocks (one for iPhone, the other for iPad) associated with a given key string. The second is for retrieving an appropriate block for the current device’s idiom. You could easily understand how to use this if you read this article. The demo project with full source codes are below:

Read More

IconUtility resizes an image into the following iPhone/iPad related icon sizes1:

  • Icon.png – 57×57 pixels application icon for standard resolution iPhone
  • Icon@2x.png – 114×114 pixels application icon for high resolution iPhone 4
  • Icon-72.png – 72×72 pixels application icon for iPad
  • Icon-Small.png – 29×29 pixels settings icon for standard resolution iPhone
  • Icon-Small@2x.png – 58×58 pixels settings icon for high resolution iPhone
  • Icon-Small-50.png – 50×50 pixels settings icon for iPad

To use it, simply drag and drop an image onto the app, then save images. IconUtility creates a folder onto your desktop that contains appropriate images. You can download the app and check its source at:

Footnotes

  1. icon size description from Updating for the iPhone 4 retinal display – Blog – Use Your Loaf []
Read More

» Movie for iPad users
» Movie for iPhone users

I am pleased to announce that my new iPad app “Pscope for iPad” is released on App Store at July 01, 2010. Pscope (Pentagonal kaleidoscope) is a kaleidoscope-like image generator interacting with a user’s touch. Using photo images, Pscope displays pentagonal-shaped image segments spread on the screen.

General kaleidoscope iPhone/iPad apps on App Store uses a triangle patch as its mirror segment. Using several unique patterns of pentagonal mirror tiling, Pscope gives a user more unexpected and surprising experience. The generated image animates according to the user’s finger place touching on the screen. The user can freely customize segments’ size and shape as well as tiling pattern with 14 different types of pentagonal tilings human beings ever found (see below).

Unlike most kaleidoscope iPhone apps, Pscope uses a photography or image as its input instead of using camera data. This is just because iPad does not have any camera function. However thanks to a larger screen of iPad, one will have richer experience than on the screen of iPhone.

Here is several examples how Pscope for iPad works.

– An input image that I made long time ago (from [Flash] fla06 – boreal-kiss.com).

– Generated image by Pscope using Cairo pentagonal tiling

– Generated image by Pscope using Floret pentagonal tiling

– Generated image by Pscope using Prismatic pentagonal tiling

You can find more info at Pscope’s web site:

» Pscope for iPad

Pscope for iPad is now on App Store for $1.99:

Related web resources

Read More