Wednesday, July 1, 2009
Wednesday, July 1, 2009  0 Comments   Links to this post   

My wife was in really slow moving traffic on 128 tonight heading up to Winchester, MA. She sent me this picture from her Blackberry:
That's right, a little bit of awesomeness all the way from the City of Champions right here. Saweeeeeet.

Labels: , ,

Monday, June 29, 2009
Monday, June 29, 2009  0 Comments   Links to this post   

If you are using the 3.0 iPhone SDK, you'll notice that by default Xcode only shows you 3.0 as a target (Simulator and device). Before you were able to target all the SDKs you had installed. I personally don't worry about this default behavior, but when you're building an iPhone application, you may want to target previous SDKs.

I read about this online someplace, and this will get 2.x available again.

  1. Select your project file and Get Info.
  2. Under the General tab, you'll see a drop down for Base SDK for All Configurations and choose your SDK there.
  3. You're done. You'll see all the SDKs listed now in the normal drop down you're used to using.

Labels:


This one goes back quite a while, and you've probably never heard of James Last. Which is a bit understandable, because the only reason I know of James Last is through my father.

When I was a child (not too much older than the age my own son is right now), my father had a pretty extensive collection of classical LPs and some 8-tracks. He had a large home system with huge BA wooden speakers, tube-powered amplifiers, the best needle in the business, etc.

We used to make fun of his collection of music as being old fogey-type stuff, but we were really just trying to act cool. Some of it was amazing and fun. I've apologized several times in the past about how we used to make fun of this stuff. In many ways, classical and ethnic music is more powerful than any "spirit of the decade" music could dream of being.

My sister and I used to play the 8-track of James Last's Russia. A few of the tracks any way. You'd have to click through spots on the tape and wait for your song to start, I remember four rectangular green lights that would tell you which approximate spot the tape was currently in. I don't remember if you could flip the tape upside down or not, I think so.

Anyway... we used to play song two: "Kalinka" (an example only video link) which slowly builds up with choir to result in ripping horns and a thunderous beat with some Russian chanting (well, perhaps not chanting but we didn't know what they were singing). We used to bounce off the walls laughing and having a good time.

Another favorite was "Russian Folk Dance" (Russischer Volkstanz) - which has a similar pattern to Kalinka. Mad fun.

A few years ago my father gave me that 8-track from his collection in the hopes to transfer it to CD. I never got around to it, I'd have to go to a place with the capability, pay cash, etc. But it always burned there in the back of my mind. For a few years whenever I remembered that album, I'd take a spin around the internet looking for it.

Now that I actually have this album, you might want to look it up, it's extremely hard to find (I don't do torrents or anything like that so I can't help you there), but if you're up for some really awesome ethnic music with true power behind it (I'm not talking about Polkas here, I'm taking about great horns, moving compositions, a big symphony sound with some modern instrumentation, and a great choir) then you should look into it. It's different.

It's not on iTunes, unfortunately. Get the LP if you can (if you can play those anymore).

Perhaps my father, my sister and myself will be the only ones who really enjoy this album and that's fine with me, I just wanted to put it out there. I am going to soak in "Nicht der Wind" (Not the Wind) for the fifth time now. Headphones up.

Ahhh.

Labels: , ,


I just looked into sdegutis's CocoaREST library (for Cocoa and Cocoa Touch platforms) - which allows developers to interact with RESTful APIs.

It's mainly targeted at Twitter at the moment, but many more services are under development and you can add extend support for others (ie. extend Twitter support for use with it's Search API). Using it is actually fairly easy... build the next great Twitter client!

Here is a quick screen-shot taken of Tweetie running beneath the included example OS X desktop application:


Check this library out if you're at all interested in using it. It rocks.

I have no idea why it happens, but I do know that it's an annoying part of developing for the iPhone. For the most part developing for OS 3 on the iPhone is a joy, really it is. But every Monday I come in to work and connect the device, fire up XCode and try to build to it finding out that I need to reboot the device before XCode can deploy to it.

It costs me only a few minutes time, but I wish it was something that would magically go away in the near future. It's monday, my caffeine quotient has not been met, it's rainy in Boston, and perhaps I'm a little gray at the moment.
Thursday, June 25, 2009
Thursday, June 25, 2009  0 Comments   Links to this post   

Update 3. Better yet:
totalCount = 0;
NSArray *d = [[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:nil];
for(NSString *s in d){
if([[s lastPathComponent] hasPrefix:@"image_"]){
totalCount++;
}
}
Update 2. Since the file structure normally gets flattened out within your iPhone application (I guess there are some compiler tricks you can do), you'll always be targeting the root of the app directory. With that in mind, you'll want to probably use some kind of naming convention to separate any special files you'd like to collect from the bundle. You can also use extension. Say collect up and get the count of all images in your bundle that are JPGs and contain "image_" in the title:
totalCount = 0;
NSArray *d = [[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:nil];
for( int i=0;i<[d count];i++){
NSString *searchForMe = @"image_";
NSString *s = [[NSString alloc] initWithString:[d objectAtIndex:i]];
NSRange range = [s rangeOfString:searchForMe];
if( range.location != NSNotFound ){
totalCount++;
}
}
Boom.

Update. I'm a moron. I should have just looked into NSBundle.h.
NSUInteger jpegCount = [[[NSBundle mainBundle] pathsForResourcesOfType:@"jpg" inDirectory:subDirName] count];

You can get the number of a type of item in your bundle on the iPhone, and this can come in very handy. No magic numbers. This code example doesn't look in a resource directory, but you could supply the inDirectory with something like @"backgrounds" and thus build up arrays of images of differing types, etc. There may be a better way of doing this (ie. if you only want to get the count of the items), but I don't know about it yet.
NSMutableArray * imageArray = [[NSMutableArray alloc] init];
NSEnumerator * imageBundlePathEnumerator = [[[NSBundle mainBundle] pathsForResourcesOfType: @"jpg" inDirectory: nil] objectEnumerator];
NSString * imageBundlePath = nil;

while (imageBundlePath = [imageBundlePathEnumerator nextObject])
{
[imageArray addObject: [[[NSImage alloc] initWithContentsOfFile: imageBundlePath] autorelease]];
}

NSLog(@"Number of images loaded : %d", [imageArray count]);

NSImage * anImage = nil;
NSEnumerator * imageEnumerator = [imageArray objectEnumerator];

while (anImage = [imageEnumerator nextObject])
{
NSLog(@"image = %@", anImage);
}
Tada. I hope to find some more examples.

Labels: ,

Friday, June 12, 2009
Friday, June 12, 2009  0 Comments   Links to this post   

Pittsburgh is yet again the City of Champions. We win a SuperBowl and a Stanley Cup. For a city to win one championship is special. Amazing win tonight beating Detroit in their own building where they had been so dominant.

Well done. Enjoy Pittsburgh... get to raise that banner in a new barn.

I ordered my gear a few minutes after the players skated around with the cup and it's all already backordered. Oh well, I can wait a little while.

"Lord Stanley, Lord Stanley, gimme the brandy!"

I didn't attend Flashbelt. I have only read multiple tweets and blog postings about what happened. You can read more about that here.

I personally think that there is no place for this kind of thing at a paid professional conference. If it was held in the corner of a bar with cigars, beers, a laptop & a projector, I wouldn't think it was appropriate either.

There, I said it. Let's just hope this kind of thing never happens again.
Thursday, June 11, 2009
Thursday, June 11, 2009  0 Comments   Links to this post   

1. I can't wait for Apple to include Safari-specific audio controls. Too many websites activate Flash video audio by default and it's jarring.

2. I can't wait for Safari for Snow Leopard to allow plugins to crash without bringing the browser down with it.

Thread 14 Crashed:
0 com.apple.CoreFoundation 0x914663cb CFReadStreamGetStatus + 43
1 ...romedia.Flash Player.plugin 0x176939d1 0x173b8000 + 2996689
2 ...romedia.Flash Player.plugin 0x1768c43f 0x173b8000 + 2966591
3 ...romedia.Flash Player.plugin 0x1768c713 0x173b8000 + 2967315
4 ...romedia.Flash Player.plugin 0x1768c7c1 0x173b8000 + 2967489
5 ...romedia.Flash Player.plugin 0x1746b727 0x173b8000 + 735015
6 ...romedia.Flash Player.plugin 0x1746bab3 0x173b8000 + 735923
7 ...romedia.Flash Player.plugin 0x1746bf69 0x173b8000 + 737129
8 ...romedia.Flash Player.plugin 0x1746c362 0x173b8000 + 738146
9 ...romedia.Flash Player.plugin 0x1746c68d 0x173b8000 + 738957
10 ...romedia.Flash Player.plugin 0x176935ff 0x173b8000 + 2995711
11 libSystem.B.dylib 0x91fdc155 _pthread_start + 321
12 libSystem.B.dylib 0x91fdc012 thread_start + 34
Wednesday, June 10, 2009
Wednesday, June 10, 2009  0 Comments   Links to this post   

The Pittsburgh Steelers got their rings yesterday and then many proceeded to go over to watch the Penguins playoff game versus the Red Wings. These rings are simply enormous, gaudy, and I think are pretty beautiful.
Thursday, May 28, 2009
Thursday, May 28, 2009  2 Comments   Links to this post   

While developing for the Mac or the iPhone, you're going to bump heads with the TERMINATING_DUE_TO_UNCAUGHT_EXCEPTION a bit. While this is nominally useful information, you never are told where the exception happened, only the reason that it did. If your application isn't very large in scope, this may be all the information you'll need to debug the problem. However, for larger applications this isn't the best.

One thing I just discovered is that you can have Xcode automagically place a breakpoint where the exception occurs, thus showing you just where the exception was thrown. Paired with the information on why, this is a big help in debugging.

To set this up, open up your Breakpoints window (in my version of Xcode I double-click on the Breakpoints items in the editor window Groups & Files tree control. You'll see a breakpoint item "Double-Click for Symbol" - set the breakpoint to "objc_exception_throw" and you're done. It should look something like this:
Now when you get an exception, you should be able to click the exposed line in the debugger stack trace which will take you to the offending line of code in your project.

Labels: , ,


[per riq] Since cosos2d v0.7.3, you can specify the texture's pixel format of your PNG/TIFF/BMP/GIF images.
The texture's pixel format is the way the image is stored in GPU memory.

Possible pixel formats:
  • RGBA8888 (32-bit) (kTexture2DPixelFormat_RGBA8888)
  • RGBA4444 (16-bit) (kTexture2DPixelFormat_RGBA4444)
  • RGB5_A1 (16-bit)(kTexture2DPixelFormat_RGB5A1)
  • RGB565 (16-bit) (kTexture2DPixelFormat_RGB565)
RGBA8888:
  • 8 bits are assigned to the red channel, 8 bits to the green channel, 8 bits to the blue channel and 8 bits to the alpha channel.
  • Use this pixel format when you need the maximum possible quality for your image.
  • But it will consume the double of memory compared to 16-bit textures. Memory is a precious resource on the iPhone
  • Usually it is also slower to render.
  • Useful for: background image of your intro scene, and for images with lots of gradient colors
RGBA4444:
  • 4 bits are assigned to the red channel, 4 bits to the green channel, 4 bits to the blue channel, and 4 bits to the alpha channel
  • It gives you good quality in all channels, good speed, good memory consumption.
  • Useful for: sprites that have different values of transparency
RGB5A1:
  • 5 bits are assigned to the red channel, 5 bits to the green channel, 5 bits to the blue channel, and only 1 bit to the alpha channel
  • It gives you good quality in RGB channels but poor quality on the A channel. It also gives you good speed and good memory consumption.
  • Useful for: sprites that have transparent parts, but the transparency is either On or Off
RGB565:
  • 5 bits are assigned to the red channel, 6 bits to the green channel, and 5 bits to the blue channel. It has no alpha channel support
  • It gives you the best possible quality for 16-bit textures, but without alpha channel support.
  • Useful for: background images in your game.
The default pixel format in v0.7.3 is RGBA8888.

How to use it:
// Set the pixel format before loading the image
// RGBA 8888 image (32-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA8888];
Sprite *sprite1 = [Sprite spriteWithFile:@"test-rgba1.png"];

// Set the pixel format before loading the image
// RGBA 4444 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGBA4444];
Sprite *sprite2 = [Sprite spriteWithFile:@"test-rgba2.png"];

// Set the pixel format before loading the image
// RGB5A1 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGB5A1];
Sprite *sprite3 = [Sprite spriteWithFile:@"test-rgba3.png"];

// Set the pixel format before loading the image
// RGB565 image (16-bit)
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_RGB565];
Sprite *sprite4 = [Sprite spriteWithFile:@"test-rgba4.png"];

// restore the default pixel format
[Texture2D setDefaultAlphaPixelFormat:kTexture2DPixelFormat_Default];

Labels: , ,

Wednesday, May 13, 2009
Wednesday, May 13, 2009  0 Comments   Links to this post   

For my previous post I showed you how you can cache in memory images from URLs... however, what if the device is not able to connect to a network? The previous example will hang and eventually bomb back to the springboard because it's not coded to handle that condition.

For me this network detection thing was a bit of a Holy Grail item. I'd seen a few examples around from Apple that seemed like they used tons of code to get the job done (or maybe I just didn't understand their code well enough yet). Then I read online about a seismic XML tutorial from Apple that did network detection.

I popped open the project in the Xcode Documentation window and started checking out the .h and .m files. I saw the implementation they used, and it didn't involve tons of code. And after testing it, it works just fine for the moment.

I've since been told that I could use a separate thread and populate the initial UIImageViews with a stock image, and the threaded process would fetch and place the artwork as needed (to allow for initial smooth scrolling). I don't know enough about that yet though, so this will have to do.

Make sure you Add the SystemConfiguration.framework to your project, and include it in your .m (#import ).

In your .h file, define a BOOL, I called mine "availableNetwork" - you don't need to assign it as a property, just up in the interface block. Make sure you also define the method in the .h... -(BOOL)isDataSourceAvailable;

Here are the two methods I'm using to report back network status (in my .m):
- (BOOL)isDataSourceAvailable {

static BOOL checkNetwork = YES;
static BOOL _isDataSourceAvailable = NO;
if (checkNetwork) { // Since checking the reachability of a host can be expensive, cache the result and perform the reachability check once.
checkNetwork = NO;
Boolean success;
const char *host_name = "google.com"; //pretty reliable :)
SCNetworkReachabilityRef reachability = SCNetworkReachabilityCreateWithName(NULL, host_name);
SCNetworkReachabilityFlags flags;
success = SCNetworkReachabilityGetFlags(reachability, &flags);
_isDataSourceAvailable = success && (flags & kSCNetworkFlagsReachable) && !(flags & kSCNetworkFlagsConnectionRequired);
CFRelease(reachability);
}
return _isDataSourceAvailable;
}
That's the method we'll call when we load our view, and set our "availableNetwork" value to. loadView is triggered before viewDidLoad.
- (void)loadView {

availableNetwork = NO;
BOOL returnVal = [self isDataSourceAvailable];
availableNetwork = returnVal;
...
And there you have it. It's a one shot deal here, if connectivity returns, the flag won't be reset. You could always run a NSTimer that checks every now and then, or I am sure there is some kind of notification of that kind of change one could listen for... I'm not far enough along with all of this to know yet.

Labels: , ,


I have a UITableView where each cell contains a UIImageView and the contents of that are populated from a URL. This works great until you start to scroll the table, because as cells are reused they of course fetch the appropriate image through appropriate URL (updating the cell's UI), and thus cause the table to chug as it tries to scroll it.

So image caching is required. Once a URL image has been downloaded and when it's going to be used again, instead of fetching the image from URL, use a stored version of it instead. Currently I am caching these images in a NSMutableDictionary (although they could be written to the iPhone disk or into a database on the iPhone as well - for offline use and also a retained cache between application launches). While the latter approach is the ultimate correct one, here is a method to provide in-memory image caching. The key for each UIImage is the URL of the image.
- (UIImage*)imageNamed:(NSString*)imageNamed cache:(BOOL)cache
{
UIImage* retImage = [staticImageDictionary objectForKey:imageNamed];
if (retImage == nil)
{
retImage = [UIImage imageWithData:[NSData dataWithContentsOfURL:[NSURL URLWithString:imageNamed]]];
if (cache)
{
if (staticImageDictionary == nil)
staticImageDictionary = [NSMutableDictionary new];

[staticImageDictionary setObject:retImage forKey:imageNamed];
}
}
return retImage;
}

- (UITableViewCell *)tableView:(UITableView *)tableView cellForRowAtIndexPath:(NSIndexPath *)indexPath {
...
// Add a view for the image (this is in section if cell = nil)
NSString *tmp = [NSString stringWithFormat:@"%@", [[photoArray objectAtIndex:row] objectForKey:@"url"]];
holder = [[[UIImageView alloc] initWithFrame:CGRectMake( 13, 2, 48, 50)] autorelease];
holder.tag = 4;
holder.contentMode = UIViewContentModeScaleToFill;

// Here we either load from the web or we cache it...
UIImage *ret = [self imageNamed:tmp cache:YES];
holder.image = ret;
...
[cell.contentView addSubview:holder];
...
This works GREAT so far, you get a little initial stutter on long lists, but once the images are loaded up, you're good to go. Since I am not currently using tons of images, memory should be okay (to keep them all around like this). Of course using the disk is going to be the ultimate solution... one I will work up next. Even for small lists it might be okay to use (if you don't plan on the images changing much...)
Tuesday, May 12, 2009
Tuesday, May 12, 2009  0 Comments   Links to this post   

If you develop in Objective-C and ever tire of setting up instance variables and then typing up properties and then coding up the matching implementation stuff, you know that after a while you've spent a ton of timing typing monotonous things.

Not great.

Kevin Callahan has written a tool called Accessorizer that runs stand-alone from Xcode, but can work pretty harmoniously with it saving you oodles and oodles of coding time. It's very customizable and the site contains a few videos to show you how it works.
gotoAndStop( topOfPage );